Springmvc View源碼分析

View

public interface View{
     String RESPONSE_STATUS_ATTRIBUTE = View. class .getName()+ ".responseStatus" ;
     String PATH_VARIABLES = View. class .getName()+ ".pathVariables" ;
     String getContentType();
     void r ender(Map<String,?>model,HttpServletRequest request,HttpServletResponse response) throws Exception;
}

getContentType : 獲取 ContentType
render: 渲染視圖方法,傳入了 request,response,model 躬审; model 中包含了在 controller 中設(shè)置的屬性痹愚,在視圖渲染時(shí)可以直接使用

AbstractView

AbstractView 中直接看 render 方法:

public void render(Map<String,?>model,HttpServletRequest request,HttpServletResponse response) throws Exception{
     if ( logger .isTraceEnabled()){
            logger .trace( "Renderingviewwithname'" + this . beanName + "'withmodel" +model+ "andstaticattributes" + this . staticAttributes) ;
     }
     Map<String,Object> mergedModel = createMergedOutputModel(model,request,response);
     prepareResponse(request,response);
     renderMergedOutputModel(mergedModel,request,response);
}

createMergedOutputModel :這個(gè)方法是合并所有的數(shù)據(jù) ( 主要是路徑參數(shù)琼懊,靜態(tài)參數(shù)优幸,以及 controller 中設(shè)置的 model)

protected Map<String,Object> createMergedOutputModel(Map<String,?>model,HttpServletRequest request,HttpServletResponse response){
     Map<String,Object> pathVars= this . exposePathVariables ?(Map<String,Object>)request.getAttribute(View. PATH_VARIABLES ): null ;
     // 計(jì)算出共有多少個(gè)屬性
     int size= this . staticAttributes .size();
     size+=(model!= null )?model.size(): 0 ;
     size+=(pathVars!= null )?pathVars.size(): 0 ;
     // 創(chuàng)建 hashmap , 初始化大小 size
     Map<String,Object> mergedModel= new HashMap<String,Object>(size);
     mergedModel.putAll( this . staticAttributes );
     if (pathVars!= null ){
          mergedModel.putAll(pathVars);
     }
     if (model!= null ){
          mergedModel.putAll(model);
     }
     //ExposeRequestContext?
     if ( this . requestContextAttribute != null ){
          mergedModel.put( this . requestContextAttribute ,createRequestContext(request,response,mergedModel));
     }
     return mergedModel;
}

pre pareResponse : 準(zhǔn)備方法筒主,如果在渲染之前需要做一些工作建钥,那么可以放入到這個(gè)方法中

protected void prepareResponse (HttpServletRequest request,HttpServletResponse response){
     if (generatesDownloadContent()){
          response.setHeader( "Pragma" , "private" );
          response.setHeader( "Cache-Control" , "private,must-revalidate" );
     }
}

在 AbstractView 中藤韵,默認(rèn)是設(shè)置了 response 的 header 信息
renderMergedOutputModel :根據(jù)合并的 model 信息來渲染視圖,這是個(gè)抽象方法熊经,具體如何渲染根據(jù)子類來實(shí)現(xiàn)
protected abstract void renderMergedOutputModel(Map<String,Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception;
AbstractUrlBasedView
這個(gè)類主要只完成一個(gè)功能泽艘,添加了一個(gè)屬性u(píng)rl,主要是給視圖指定一個(gè)url路徑
InternalResourceView
這個(gè)是默認(rèn)的視圖類,主要是jsp或者其他視圖資源的一個(gè)包裝镐依。把model中的數(shù)據(jù)存放到了request的attribute中
alwaysInclude屬性來要求返回的結(jié)果使用include方式而不是forward方式
exposeContextBeansAsAttributes屬性是否需要將當(dāng)前spring 環(huán)境中的 beans作為request attritbutes來暴露到頁面上匹涮。
exposedContextBeanNames屬性來限制能夠暴露到頁面上的spring bean的名稱列表。

protected void renderMergedOutputModel(Map<String,Object>  model,HttpServletRequest  request,HttpServletResponse  response)throws  Exception{
    //把WebApplicationContext中的一些Bean給RequestDispatcher
    HttpServletRequest  requestToExpose=getRequestToExpose(request);
    //把model中的數(shù)據(jù)作為reqest的attribute
    exposeModelAsRequestAttributes(model,requestToExpose);
    //空實(shí)現(xiàn)槐壳,子類可以覆蓋然低,放一些東西到Reqest中
    exposeHelpers(requestToExpose);
    //獲取到跳轉(zhuǎn)地址
    String  dispatcherPath  =  prepareForRendering(requestToExpose,response);
    //通過request.getRequestDispatcher(path)獲取到RequestDispatcher
    RequestDispatcher  rd=  getRequestDispatcher(requestToExpose,dispatcherPath);
    if(rd==null){
        Throw new  ServletException("CouldnotgetRequestDispatcherfor["+getUrl()+"]:Checkthatthecorrespondingfileexistswithinyourwebapplicationarchive!");
    }
    //檢查這個(gè)Request是否已經(jīng)include,或者response是否已經(jīng)commited,如果有任一一種情況,那么就用include代替forward.
    //這樣能夠保證在調(diào)用response.flushBufer()之前渲染視圖    This can be enforced by calling response.flushBuffer() (which will commit the response) before rendering the view.
    if(useInclude(requestToExpose,response)){
        response.setContentType(getContentType());
        if(logger.isDebugEnabled()){
            logger.debug("Includingresource["+getUrl()+"]inInternalResourceView'"+getBeanName()+"'");
        }
        rd.include(requestToExpose,response);
    }else{
        exposeForwardRequestAttributes(requestToExpose);
        if(logger.isDebugEnabled()){
            logger.debug("Forwardingtoresource["+getUrl()+"]inInternalResourceView'"+getBeanName()+"'");
        }
        rd.forward(requestToExpose,response);
    }
}

AbstractExcelView

@Override
protected final void renderMergedOutputModel(
Map<String,Object> model,HttpServletRequest request,HttpServletResponse response)throws Exception{
    HSSFWorkbook workbook;
    if(this.url!=null){
        //根據(jù)指定的excel文件路徑創(chuàng)建HSSFWorkbook對(duì)象
        workbook=getTemplateSource(this.url,request);
    }
    else{
        workbook=new HSSFWorkbook();
        logger.debug("CreatedExcelWorkbookfromscratch");
    }
    //構(gòu)建excel文件的具體內(nèi)容宏粤,抽象類脚翘,讓子類實(shí)現(xiàn)
    buildExcelDocument(model,workbook,request,response);
    //Setthecontenttype.
    response.setContentType(getContentType());
    //Flushbytearraytoservletoutputstream.
    ServletOutputStreamout=response.getOutputStream();
    workbook.write(out);
    out.flush();
}

完成通用的excel導(dǎo)出,通過設(shè)置excel模板地址绍哎,編寫excel模板来农,使用model中的數(shù)據(jù)填充模板,最后導(dǎo)出excel
1.首先創(chuàng)建excel模板文件:excel-report.xls


約定F表示數(shù)據(jù)項(xiàng)崇堰,F(xiàn)表示數(shù)據(jù)項(xiàng)沃于,P表示數(shù)據(jù)項(xiàng)之前的數(shù)據(jù)(標(biāo)題等)涩咖,V表示統(tǒng)計(jì)信息,V表示統(tǒng)計(jì)信息繁莹,V{nbsp}表示空白單元格也可以什么都不填檩互;如果要設(shè)置數(shù)據(jù)行格式為數(shù)字:n;
默認(rèn)的格式是:label
導(dǎo)出的最后效果圖咨演,數(shù)據(jù)都是測(cè)試數(shù)據(jù):
image

2.創(chuàng)建模板解析類闸昨,解析出所有的單元格存放到對(duì)應(yīng)的List中,parameterCells薄风,fieldCells饵较,variableCells

    /**
    *導(dǎo)出Excel的模板對(duì)象
    */
    public class ExcelTemplate{
        private List<HSSFCell> parameterCells=new ArrayList<>();
        private List<HSSFCell> fieldCells=new ArrayList<>();
        private List<HSSFCell> variableCells=new ArrayList<>();
        private HSSFWorkbook workbook;
        public ExcelTemplate(HSSFWorkbook workbook){
            Assert.notNull(workbook,"workbook can not is null");
            this.workbook=workbook;
            parse();
        }
        /**
        *解析Excel模板
        */
        private void parse(){
            HSSFSheet sheet=workbook.getSheetAt(0);
            Assert.notNull(sheet,"模板工作表對(duì)象不能為空!");
            for(intk=0;k<sheet.getLastRowNum()+1;k++){
                HSSFRow cells=sheet.getRow(k);
                for(int j=0;j<cells.getLastCellNum()+1;j++){
                    HSSFCellcell=cells.getCell(j);
                    if(cell==null){
                        continue;
                    }
                    StringcellContent=cell.getStringCellValue();
                    if(StringUtils.isEmpty(cellContent)){
                        continue;
                    }
                    if(cellContent.contains("$P")||cellContent.contains("$p")){
                        parameterCells.add(cell);
                    }elseif(cellContent.contains("$F")||cellContent.contains("$f")){
                        fieldCells.add(cell);
                    }elseif(cellContent.contains("$V")||cellContent.contains("$v")){
                        variableCells.add(cell);
                    }
                }
            }
        }
        /**
        *增加一個(gè)參數(shù)對(duì)象
        */
        public void addParameterCell(HSSFCell cell){
            parameterCells.add(cell);
        }
        /**
        *增加一個(gè)字段對(duì)象
        */
        public void addFieldCell(HSSFCell cell){
            fieldCells.add(cell);
        }
        //省略getter setter
    }

3.創(chuàng)建存放模板需要展示的數(shù)據(jù)類ExcelData

    /**
    *Excel數(shù)據(jù)對(duì)象
    */
    public class ExcelData{
        //下載文件時(shí)顯示的名稱
        private String downloadFileName;
        /**
        *Excel參數(shù)元數(shù)據(jù)對(duì)象
        */
        private Map parameters=new HashMap();
        private Map variables=new HashMap();
        /**
        *Excel集合元對(duì)象
        */
        private List fields=new ArrayList<>();
        public ExcelData(){
        }
        /**
        *構(gòu)造函數(shù)
        *
        *@param parameters元參數(shù)對(duì)象
        *@param pList集合元對(duì)象
        */
        public ExcelData(Map parameters,Map variables,List pList){
            setParameters(parameters);
            setFields(pList);
            setVariables(variables);
        }
        @SuppressWarnings("unchecked")
        public ExcelData addField(Object value){
            this.fields.add(value);
            returnthis;
        }
        @SuppressWarnings("unchecked")
        public ExcelData addParameter(String key,Object value){
            this.parameters.put(key,value);
            returnthis;
        }
        @SuppressWarnings("unchecked")
        public ExcelData addVariable(String key,Object value){
            this.variables.put(key,value);
            returnthis;
        }
        //省略getter setter...
    }

4.創(chuàng)建數(shù)據(jù)填充器ExcelFiller,根據(jù)ExcelTempleate解析出來的模板和ExcelData來填充excel

/**
*Excel數(shù)據(jù)填充器
*/
public class ExcelFiller{
    /**
    *Excel模板數(shù)據(jù)類型<br>
    *number:數(shù)字類型
    */
    public static final StringE XCEL_TPL_DATA_TYPE_NUMBER="number";
    /**
    *Excel模板數(shù)據(jù)類型<br>
    *number:文本類型
    */
    public static final String EXCEL_TPL_DATA_TYPE_LABEL="label";
    private static final Logger logger=LoggerFactory.getLogger(ExcelFiller.class);
    private ExcelTemplate excelTemplate=null;
    private ExcelData excelData=null;
    /**
    *構(gòu)造函數(shù)
    *
    *@parampExcelTemplate
    *@parampExcelData
    */
    publicExcelFiller(ExcelTemplate pExcelTemplate,ExcelData pExcelData){
        setExcelData(pExcelData);
        setExcelTemplate(pExcelTemplate);
        ConvertUtils.deregister(Date.class);
        DateConverter dateConverter=new DateConverter();
        dateConverter.setPattern("yyyy-MM-ddHH:mm:ss");
        ConvertUtils.register(new ConverterFacade(dateConverter),Date.class);
    }
    /**
    *數(shù)據(jù)填充將ExcelData填入excel模板
    *
    *@returnByteArrayOutputStream
    */
    publicvoidfill(){
        try{
            HSSFWorkbook workbook=this.excelTemplate.getWorkbook();
            HSSFSheet sheet=workbook.getSheetAt(0);
            fillParameters(sheet);
            fillFields(sheet);
        }catch(Exceptione){
            logger.error("基于模板生成可寫工作表出錯(cuò)了!");
            e.printStackTrace();
        }
    }
    /**
    *寫入?yún)?shù)對(duì)象
    *
    *@paramwSheet
    */
    private void fillParameters(HSSFSheet wSheet){
        List<HSSFCell> parameterCells=getExcelTemplate().getParameterCells();
        Map parameters=getExcelData().getParameters();
        for(HSSFCellcell:parameterCells){
            String cellContent=cell.getStringCellValue().trim();
            String key=getKey(cellContent);
            String type=getType(cellContent);
            HSSFRow row=wSheet.getRow(cell.getRowIndex());
            row.removeCell(cell);
            HSSFCell hssfCell=row.createCell(cell.getColumnIndex());
            hssfCell.setCellStyle(cell.getCellStyle());
            if(type.equalsIgnoreCase(EXCEL_TPL_DATA_TYPE_NUMBER)){
                BigDecimal convertValue=(BigDecimal)ConvertUtils.convert(parameters.get(key),BigDecimal.class);
                hssfCell.setCellType(Cell.CELL_TYPE_NUMERIC);
                hssfCell.setCellValue(convertValue.doubleValue());
            }else{
                String convertValue=(String)ConvertUtils.convert(parameters.get(key),String.class);
                hssfCell.setCellType(Cell.CELL_TYPE_STRING);
                hssfCell.setCellValue(convertValue);
            }
        }
    }
    /**
    *寫入表格字段對(duì)象
    *
    *@paramwSheet
    *@throwsException
    */
    private void fillFields(HSSFSheet wSheet) throws Exception{
        List<HSSFCell> fieldCells=getExcelTemplate().getFieldCells();
        List fields=getExcelData().getFields();
        for(intj=0;j<fields.size();j++){
            BeanWrapper beanWrapper=new BeanWrapperImpl(fields.get(j));
            HSSFRowrow=null;
            for(HSSFCellcell:fieldCells){
                String cellContent=cell.getStringCellValue().trim();
                String key=getKey(cellContent);
                String type=getType(cellContent);
                if(row==null){
                    row=wSheet.createRow(cell.getRowIndex()+j);
                }
                HSSFCellhssfCell=row.createCell(cell.getColumnIndex());
                hssfCell.setCellStyle(cell.getCellStyle());
                if(type.equalsIgnoreCase(EXCEL_TPL_DATA_TYPE_NUMBER)){
                    BigDecimal convertValue=(BigDecimal)ConvertUtils.convert(beanWrapper.getPropertyValue(key),BigDecimal.class);
                    hssfCell.setCellType(Cell.CELL_TYPE_NUMERIC);
                    hssfCell.setCellValue(convertValue.doubleValue());
                }else{
                    String convertValue=(String)ConvertUtils.convert(beanWrapper.getPropertyValue(key),String.class);
                    hssfCell.setCellType(Cell.CELL_TYPE_STRING);
                    hssfCell.setCellValue(convertValue);
                }
            }
        }
        HSSFCell cell=fieldCells.get(0);
        int rowIndex=fields.size()+cell.getRowIndex();
        fillVariables(wSheet,rowIndex);
    }
    /**
    *寫入變量對(duì)象
    */
    private void fillVariables(HSSFSheet wSheet,int rowIndex){
        List<HSSFCell> variableCells=getExcelTemplate().getVariableCells();
        Map variables=getExcelData().getVariables();
        HSSFRow row=wSheet.createRow(rowIndex);
        for(HSSFCellcell:variableCells){
            String cellContent=cell.getStringCellValue().trim();
            String key=getKey(cellContent);
            String type=getType(cellContent);
            HSSFCell hssfCell=row.createCell(cell.getColumnIndex());
            hssfCell.setCellStyle(cell.getCellStyle());
            if(type.equalsIgnoreCase(EXCEL_TPL_DATA_TYPE_NUMBER)){
                BigDecimal convertValue=(BigDecimal)ConvertUtils.convert(variables.get(key),BigDecimal.class);
                hssfCell.setCellType(Cell.CELL_TYPE_NUMERIC);
                hssfCell.setCellValue(convertValue.doubleValue());
            }else{
                String content=(String)ConvertUtils.convert(variables.get(key),String.class);
                if(StringUtils.isEmpty(content)&&!key.equalsIgnoreCase("nbsp")){
                    content=key;
                }
                hssfCell.setCellType(Cell.CELL_TYPE_STRING);
                hssfCell.setCellValue(content);
            }
        }
    }
    /**
    *獲取模板鍵名
    *
    *@parampKey模板元標(biāo)記
    *@return鍵名
    */
    private static String getKey(String pKey){
        String key=null;
        int index=pKey.indexOf(":");
        if(index==-1){
            key=pKey.substring(3,pKey.length()-1);
        }else{
            key=pKey.substring(3,index);
        }
        return key;
    }
    /**
    *獲取模板單元格標(biāo)記數(shù)據(jù)類型
    *
    *@parampType模板元標(biāo)記
    *@return數(shù)據(jù)類型
    */
    private static String getType(String pType){
        String type=EXCEL_TPL_DATA_TYPE_LABEL;
        if(pType.contains(":n")||pType.contains(":N")){
            type=EXCEL_TPL_DATA_TYPE_NUMBER;
        }
        return type;
    }
    //省略getter setter
}

5.創(chuàng)建excel視圖類AppExcelView

public class AppExcelView extends AbstractExcelView{
        /**
        *excel的數(shù)據(jù)對(duì)象ExcelData放到model中的key
        */
        public static final String EXCEL_DATA_MODEL_KEY = AppExcelView.class + "_ExcelData";
        public AppExcelView(){
        }
        @Override
        protected void buildExcelDocument(Map<String,Object>model,HSSFWorkbook workbook,HttpServletRequest request,HttpServletResponse response)throwsException{
            ExcelData excelData=(ExcelData)model.get(EXCEL_DATA_MODEL_KEY);
            String downloadFileName=WebUtils.encodeChineseDownloadFileName(request,excelData.getDownloadFileName());
            response.setHeader("Content-Disposition","attachment;filename="+downloadFileName+";");
            ExcelFiller excelFiller=new ExcelFiller(new ExcelTemplate(workbook),excelData);
            excelFiller.fill();
        }
    }

6.創(chuàng)建一個(gè)視圖的解析器ReportViewResolver

public class ReportViewResolver extends AbstractCachingViewResolver implements Ordered{
        private static final String EXCEL_URL_PREFIX="excel:";
        private String prefix="";
        private in torder=Integer.MAX_VALUE;
        @Override
        protected ViewloadView(String viewName,Locale locale)throws Exception{
            //Checkforspecial"excel:"prefix.
            if(viewName.startsWith(EXCEL_URL_PREFIX)){
                String excelViewName=viewName.substring(EXCEL_URL_PREFIX.length());
                AppExcelView appExcelView=BeanUtils.instantiateClass(AppExcelView.class);
                appExcelView.setUrl(getPrefix()+excelViewName);
                return applyLifecycleMethods(excelViewName,appExcelView);
            }
            returnnull;
        }
        private View applyLifecycleMethods(String viewName,AbstractView view){
        return(View)getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view,viewName);
        }
        //getter  setter
    }

7.在dispatchServlet.xml中配置視圖解析器

<!--視圖解析器-->
<bean class="org.springframework.web.servlet.view.ReportViewResolver">
    <property name="prefix" value="/report/"/>
    <property name="order" value="1"/>
</bean>

8.編寫controller代碼遭赂,創(chuàng)建ExcelData對(duì)象

    @Controller
    @RequestMapping("/report/")
    publicclassReportController{
        @RequestMapping(value="excel",method=RequestMethod.GET)
        publicStringexcel(Modelmodel){
            ExcelData excelData=new ExcelData();
            excelData.addParameter("reportTitle","test");
            excelData.addParameter("jbr","SilentWu");
            excelData.addParameter("amount",100);
            excelData.addParameter("date",new Date());
            excelData.addVariable("count",50);
            excelData.setFields(loadProjects());
            excelData.setDownloadFileName("test.xls");
            //把ExcelData對(duì)象放入到model中循诉,key要用這個(gè)
            model.addAttribute(AppExcelView.EXCEL_DATA_MODEL_KEY,excelData);
            return"excel:excel/excel-report";
        }
        private List<Project> loadProjects(){
            List<Project> projects=new ArrayList<>();
            for(inti=0;i<10;i++){
                Project project=new Project();
                project.setProjectId(i);
                project.setProjectName("test-"+i);
                projects.add(project);
            }
            return projects;
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市撇他,隨后出現(xiàn)的幾起案子茄猫,更是在濱河造成了極大的恐慌,老刑警劉巖困肩,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件划纽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡僻弹,警方通過查閱死者的電腦和手機(jī)阿浓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹋绽,“玉大人芭毙,你說我怎么就攤上這事⌒对牛” “怎么了退敦?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蚣抗。 經(jīng)常有香客問我侈百,道長,這世上最難降的妖魔是什么翰铡? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任钝域,我火速辦了婚禮,結(jié)果婚禮上锭魔,老公的妹妹穿的比我還像新娘例证。我一直安慰自己,他們只是感情好迷捧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布织咧。 她就那樣靜靜地躺著胀葱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪笙蒙。 梳的紋絲不亂的頭發(fā)上抵屿,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音捅位,去河邊找鬼轧葛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绿渣,可吹牛的內(nèi)容都是我干的朝群。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼中符,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了誉帅?” 一聲冷哼從身側(cè)響起淀散,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚜锨,沒想到半個(gè)月后档插,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亚再,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年郭膛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氛悬。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡则剃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出如捅,到底是詐尸還是另有隱情棍现,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布镜遣,位于F島的核電站己肮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏悲关。R本人自食惡果不足惜谎僻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寓辱。 院中可真熱鬧艘绍,春花似錦、人聲如沸讶舰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至般甲,卻和暖如春肋乍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背敷存。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工墓造, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锚烦。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓觅闽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涮俄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蛉拙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容