《SpringBoot+Vue》Chapter04 SpringBoot整合Web開發(fā)

返回JSON數(shù)據(jù)

默認實現(xiàn)

依賴

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

在springboot web依賴中加入了jackson-databind作為JSON處理器

創(chuàng)建一個實體類對象

public class Book {
    private String name;
    private String author;
    @JsonIgnore
    private Float price;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date publicationDate;
}

創(chuàng)建BookController

@Controller
public class BookController {
    @GetMapping("/book")
    @ResponseBody
    public Book book() {
        Book book = new Book("bookName", "bookAuthor", 100f, new Date());
        return book;
    }
}

自定義Json轉(zhuǎn)換器

Gson

Gson是google的一個開源JSON解析框架腔长。使用Gson秉馏,需要加入Gson依賴娩脾,并去除默認的jackson-databind

 <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
</dependency>

SpringBoot中默認提供了Gson自動轉(zhuǎn)換咙咽,因此Gson的依賴添加后,就可以直接使用Gson悲柱。但是在Gson進行轉(zhuǎn)換時,如果想對日期數(shù)據(jù)進行格式化。需要開發(fā)者自定義HttpMessageConverter自定義HttpMessageConverter

 @Bean
    GsonHttpMessageConverter gsonHttpMessageConverter() {
        GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
        GsonBuilder gsonBuilder = new GsonBuilder();
        //設(shè)置時間格式
        gsonBuilder.setDateFormat("yyyy-MM-dd");
        //設(shè)置gson解析時遇到protected修飾的字段被過濾掉
        gsonBuilder.excludeFieldsWithModifiers(Modifier.PROTECTED);
        Gson gson = gsonBuilder.create();
        converter.setGson(gson);
        return converter;
    }

fastjson

fastjson是阿里巴巴的一個開源JSON解析框架。是目前最快的JSON解析框架

靜態(tài)資源訪問

默認策略

SpringBoot中對于SpringMVC的自動化配置都在WebMvcAutoConfiguration類
SpringBoot默認會過濾所有的靜態(tài)資源躯砰、而靜態(tài)資源的位置一共有5個:

  • classpath:/META-INF/resources
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/
  • /


    資源文件優(yōu)先級

自定義策略

在配置文件中定義

spring.mvc.static-path-pattern=/static/**
spring.web.resources.static-locations=classpath:/static/
  • 過濾規(guī)則為/static/** 靜態(tài)資源位置為classpath:/static/

Java編碼定義

public class MyWebMvcConfig implements WebMvcConfigurer{
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry){
  registry.addResourceHandler("/static/**")
              .addResourceLocations("classpath:/static/")
}
}

文件上傳

單文件上傳

首先創(chuàng)建一個SpringBoot項目并添加spring-boot-starter-web依賴
在resources目錄下的static目錄創(chuàng)建一個upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="uploadFile" value="選擇文件">
    <input type="submit" value="上傳">
</form>
</body>
</html>

創(chuàng)建文件上傳接口

 @PostMapping("/upload")
    public String upload(MultipartFile uploadFile, HttpServletRequest req) {
        String realPath = req.getSession().getServletContext().getRealPath("/uploadFile");
        String format = sdf.format(new Date());
        File folder = new File(realPath + format);
        if (!folder.isDirectory()) {
            folder.mkdirs();
        }
        String oldName = uploadFile.getOriginalFilename();
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."), oldName.length());
        try {
            uploadFile.transferTo(new File(folder, newName));
            String filePath = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/uploadFile/" + format + newName;
            return filePath;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "上傳失敗";
    }

@ControllerAdvice

全局異常處理

@ControllerAdvice最常見的使用場景就是全局異常處理

@ControllerAdvice
public class CustomExceptionHandler {
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public void uploadException(MaxUploadSizeExceededException maxUploadSizeExceededException,
                                HttpServletResponse resp){
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = null;
        try {
            writer = resp.getWriter();
            writer.write("超出文件大小限制");
            writer.flush();
            writer.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

當(dāng)系統(tǒng)啟動時每币,標(biāo)記@ControllerAdvice就會被掃描到Spring容器中,然后在方法上添加@ExceptionHandler注解琢歇,其中定義的MaxUploadSizeExceededException.class表明該方法用來處理MaxUploadSizeExceededExceptioon類型的異常兰怠。

添加全局數(shù)據(jù)

@ControllerAdvice是一個全局數(shù)據(jù)處理組件±蠲#可以在@ControllerAdvice中使用@ModelAttribute注解配置全局數(shù)據(jù)

@ControllerAdvice
public class GlobalConfig {
    @ModelAttribute(value = "info")
    public Map<String,String> userInfo() {
        HashMap<String, String> map = new HashMap<>();
        map.put("username", "lgz");
        map.put("gender", "男");
        return map;
    }
}
  • 在全局配置中添加userInfo方法揭保,返回map,該方法有一個注解@ModelAttribute魄宏,其中的value屬性表示這條返回數(shù)據(jù)的key秸侣,而方法的返回值是返回數(shù)據(jù)的value
  • 在任意請求的Controller中,通過Model參數(shù)可以獲取map數(shù)據(jù)

請求參數(shù)預(yù)處理

@ControllerAdvice結(jié)合@InitBinder能實現(xiàn)請求參數(shù)預(yù)處理,即將表單中的數(shù)據(jù)綁定到實體類上時進行一些額外處理
例如有兩個實體類Book和Author

public class Book {
    private String name;
    private String author;
//.....getter/setter
}
public class Author {
    private String name;
    private int age;
//......getter/setter
}

Controller

@RestController
public class InitBinderController {
    @GetMapping("/book")
    public String book(Book book, Author author) {
        return book.toString() + ">>>" + author.toString();
    }
}

這樣在傳遞參數(shù)時味榛,兩個實體類中的name就會容易混淆椭坚。@ControllerAdvice結(jié)合@InitBinder可以順利解決該問題

@RestController
public class InitBinderController {
    @GetMapping("/book")
    public String book(@ModelAttribute("a") Book book,
                       @ModelAttribute("b") Author author) {
        return book.toString() + ">>>" + author.toString();
    }
}

配置@ControllerAdvice

  @InitBinder("a")
    public void init(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("b.");
    }

    @InitBinder("b")
    public void init2(WebDataBinder binder) {
        binder.setFieldDefaultPrefix("a.");
    }
  • @InitBinder("b")表示該方法是處理@ModelAttribute("b")對應(yīng)的參數(shù)的,第二個@InitBinder("a")表示該方法是處理@ModelAttribute("a")對應(yīng)的參數(shù)的

然后在瀏覽器中訪問:http://localhost:8080/book?b.name=bname&b.author=bauthor&a.name=aname&a.age=aAge即可成功地區(qū)分出name屬性

  • WebDataBinder對象中搏色,還可以設(shè)置允許的字段善茎、禁止的字段、必填字段以及驗證器等

自定義錯誤頁

@ControllerAdvice可以處理應(yīng)用級別的異常频轿,有一些容器級別的錯誤就處理不了垂涯。
在SpringBoot中,默認情況下航邢,404耕赘、500等會有統(tǒng)一的處理頁面。
SpringBoot在返回錯誤信息時不一定返回HTML頁面翠忠,而是根據(jù)實際情況返回HTML頁面或者一段JSON
SpringBoot中的錯誤默認是由BasicErrorContoller類來處理的

@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = getStatus(request);
        Map<String, Object> model = Collections
            .unmodifiableMap(getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = resolveErrorView(request, response, status, model);
        return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
    }

    @RequestMapping
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        HttpStatus status = getStatus(request);
        if (status == HttpStatus.NO_CONTENT) {
            return new ResponseEntity<>(status);
        }
        Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
        return new ResponseEntity<>(body, status);
    }

errorHtml方法用來返回錯誤HTML頁面鞠苟,error用來返回錯誤JSON
DefaultErrorViewResolver是SpringBoot中默認的錯誤信息視圖解析器,SpringBooot默認是在error目錄下查找4xx秽之、5xx的文件作為錯誤視圖当娱,找不到時會回到errorHtml中,然后使用error作為默認的錯誤頁面視圖名考榨,如果error的視圖也找不到跨细,用戶就會看到默認的錯誤提示頁面

簡單配置

如果想自定義錯誤頁面,只需要提供4xx河质、5xx的頁面即可冀惭。
如果不需要向用戶展示詳細的錯誤信息,可以把錯誤信息定義成靜態(tài)頁面掀鹅,直接在resources/static目錄下創(chuàng)建error目錄散休,然后在error目錄中創(chuàng)建錯誤展示頁面,錯誤展示頁面的命名規(guī)則有:

  • 4xx.html乐尊、5xx.html
  • 404.html戚丸、405.html、500.html
    此時當(dāng)用戶訪問一個不存在的網(wǎng)站時扔嵌,就會展示404.html中的內(nèi)容
  • 動態(tài)頁面
    如果采用視圖模板技術(shù)限府,先添加依賴,然后在templates目錄下創(chuàng)建error目錄痢缎,然后創(chuàng)建錯誤展示頁


    error目錄

CORS支持

CORS:是一種跨域資源共享技術(shù)標(biāo)準(zhǔn)胁勺,目的就是為了解決前端的跨域請求。CORS支持多種HTTP請求
定義一個Controller

@RestController
@RequestMapping("/book")
public class BookController {
    @PostMapping("/")
    public String addBook(String bookName) {
        return "receive" + bookName;
    }

    @DeleteMapping("{id}")
    public String delBook(@PathVariable("id") Long id) {
        return String.valueOf("id");
    }
}

配置跨域

跨域有兩個配置地方独旷,

  • 一個是直接在相應(yīng)的請求方法上加注解
@RestController
@RequestMapping("/book")
public class BookController {
    @PostMapping("/")
    @CrossOrigin(value = "http://localhost:8081",maxAge = 1800,allowedHeaders = "*")
    public String addBook(String bookName) {
        return "receive" + bookName;
    }

    @DeleteMapping("{id}")
    @CrossOrigin(value = "http://localhost:8081",maxAge = 1800,allowedHeaders = "*")
    public String delBook(@PathVariable("id") Long id) {
        return String.valueOf("id");
    }
}
  • @CrossOrigin中的value表示支持的域署穗,這段代碼中表示來自http://localhost:8081域的請求是支持跨域
  • maxAge表示探測請求的有效期 單位是秒
  • allowedHeaders表示允許的請求頭寥裂,*表示所有請求頭都被允許

使用全局配置 創(chuàng)建配置類Config

@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/book/**")
                .allowedHeaders("*")
                .allowedMethods("*")
                .maxAge(1800)
                .allowedOrigins("http://localhost:8081");
    }
}

配置類與XML配置

SpringBoot的配置類需要添加@Configuration注解,@ComponentScan注解會掃描所有的Spring組件蛇捌。也包括@Configuration

注冊攔截器

創(chuàng)建攔截器實現(xiàn)HanlderInterceptor接口

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandler>>>>");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandler>>>>");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion>>>>");
    }
}

攔截器中的方法將按照

preHandle->Controller->postHandle->afterCompletion
  • 只有preHandle方法返回true時后面的方法才會執(zhí)行抚恒,
  • 當(dāng)攔截器內(nèi)存在多個攔截器時postHandler在攔截器內(nèi)的所有攔截器返回成功時才會調(diào)用
  • afterCompletion只有preHandler返回true才調(diào)用
  • 若攔截器內(nèi)的第一個攔截器的preHandle返回false,則后面的方法都不執(zhí)行
    配置攔截器
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/book/**")
                .allowedHeaders("*")
                .allowedMethods("*")
                .maxAge(1800)
                .allowedOrigins("http://localhost:8081");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/hello");
    }
}

啟動系統(tǒng)任務(wù)

有一些特殊的任務(wù)需要在系統(tǒng)啟動時執(zhí)行络拌,配置文件加載俭驮,數(shù)據(jù)庫初始化等操作。SpringBoot對此提供了兩種解決方案 CommandLineRunner 和 ApplicationRunner

CommandLineRunner

SpringBoot項目在啟動時會遍歷所有CommandLineRunner的實現(xiàn)類并調(diào)用其中的run方法春贸,如果有多個實現(xiàn)類混萝,那么可以使用@Order注解對這些實現(xiàn)類的調(diào)用順序進行排序

@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("first runner"+ Arrays.toString(args));
    }
}
@Component
@Order(2)
public class MyCommandLineRunner2 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("second runner"+ Arrays.toString(args));
    }
}

  • @Order(1)注解用來描述CommandLineRunner的執(zhí)行順序,數(shù)字越小越先執(zhí)行
  • run方法中是調(diào)用的核心邏輯萍恕,參數(shù)是系統(tǒng)啟動時傳入的參數(shù)

ApplicationRunner

ApplicationRunner和CommandLineRunner基本一致逸嘀,區(qū)別主要體現(xiàn)在run方法的參數(shù)上

整合Servlet、Filter和Listener

  • @WebServlet標(biāo)記HttpServlet
  • @WebListener標(biāo)記Listener
  • @WebFilter標(biāo)記Filter
  • 在項目入口類上添加@ServletComponentScan注解允粤,實現(xiàn)對Servlet崭倘、Filter以及Listener的掃描

路徑映射

在使用頁面模板后,用戶需要通過Controller才能訪問頁面类垫,一些頁面需要在控制器中加載數(shù)據(jù)司光,然后渲染,才能顯示出來悉患。還有一些頁面在控制器中不需要加載數(shù)據(jù)残家,只是完成簡單的跳轉(zhuǎn)。對于這種頁面售躁,可以直接配置路徑映射坞淮,提高訪問速度

 @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/index").setViewName("index");
    }

配置AOP

AOP中的概念

AOP中的概念

SpringBoot支持

SpringBoot在Spring的基礎(chǔ)上對AOP的配置提供了自動化配置解決方案:spring-boot-starter-aop,使開發(fā)者能夠更加便捷地在SpringBoot項目中使用AOP

  • 添加AOP依賴
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
  • 創(chuàng)建一個測試的業(yè)務(wù)Service類
@Service
public class UserService {
    public String getUserById(Integer id) {

        System.out.println("getUserById = " + id);
        return "user";
    }
    public void deleteUserById(Integer id) {
        System.out.println("deleteUserById"+ id);
    }
}
  • 創(chuàng)建切面
@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(* com.probuing.springbootcros.service.*.* (..))")
    public void pc1() {

    }

    @Before(value = "pc1()")
    public void before(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法開始執(zhí)行");
    }

    @After(value = "pc1()")
    public void after(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法執(zhí)行結(jié)束");
    }

    @AfterReturning(value = "pc1()", returning = "result")
    public void afterRunning(JoinPoint jp, Object result) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法返回值為" + result);
    }


    @AfterThrowing(value = "pc1()", throwing = "e")
    public void afterThrowing(JoinPoint jp, Exception e) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法異常了" + e.getMessage());
    }


    @Around(value = "pc1()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        return pjp.proceed();
    }

}
  • @Aspect表明這是一個切面類
  • @Pointcut 是切入點的定義陪捷,execution中的第一個表示方法返回任意值回窘,第二個表示方法返回任意值,第二個* 表示service包下的任意類市袖,第三個*表示類中的任意方法啡直。括號中的兩個點表示方法參數(shù)任意。這里的切點表達式表示切入點為service包下所有類中的所有方法
  • @Before表示這是一個前置哦通知凌盯,該方法在目標(biāo)方法執(zhí)行之前執(zhí)行付枫,通過JoinPoint參數(shù)可以獲取目標(biāo)方法的方法名烹玉,修飾符
  • @After表示這是一個后置通知驰怎,該方法在目標(biāo)方法執(zhí)行之后執(zhí)行
  • @AfterReturning注解,表示這是一個返回通知二打,在該方法中可以獲取目標(biāo)方法的返回值县忌。@AfterReturning注解的returning參數(shù)是指返回值的變量名,對應(yīng)方法的參數(shù)。
  • @AfterThrowing症杏,表示這是一個異常通知装获,即當(dāng)目標(biāo)方法發(fā)生異常時,該方法會被調(diào)用厉颤,異常類型為Exception表示所有的異常都會進入該方法中執(zhí)行
  • @Around,表示這是一個環(huán)繞通知穴豫,環(huán)繞通知是所有通知里最強大的通知,可以實現(xiàn)前置通知逼友、后置通知精肃、異常通知以及返回通知的功能 目標(biāo)方法進入環(huán)繞通知后,通過調(diào)用ProceedingJoinPoint對象的proceed方法使目標(biāo)方法繼續(xù)執(zhí)行帜乞,開發(fā)者可以在此修改目標(biāo)方法的執(zhí)行參數(shù)司抱、返回值等,并且可以在此處理目標(biāo)方法的異常

其他設(shè)置

自定義歡迎頁

SpringBoot項目在啟動后黎烈,首先會去靜態(tài)資源路徑下查找index.html作為首頁文件习柠,若查找不到,則會去查找動態(tài)的index文件作為首頁
如果使用靜態(tài)的index.html作為項目首頁照棋,那么只需要在resources/static目錄下創(chuàng)建index.html资溃。如果使用動態(tài)頁面作為項目首頁則需要在resources/templates目錄下創(chuàng)建index.html,然后在Controller中返回邏輯視圖名必怜。

自定義favicon

favicon.ico是瀏覽器選項卡左上角的圖標(biāo)肉拓,可以放在靜態(tài)資源路徑下或者類的路徑下,靜態(tài)資源路徑下的favicon.ico優(yōu)先級高于favicon.co
將圖標(biāo)文件復(fù)制到/resources/static 目錄下

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末梳庆,一起剝皮案震驚了整個濱河市暖途,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌膏执,老刑警劉巖驻售,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異更米,居然都是意外死亡欺栗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門征峦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迟几,“玉大人,你說我怎么就攤上這事栏笆±嗳” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵蛉加,是天一觀的道長蚜枢。 經(jīng)常有香客問我缸逃,道長,這世上最難降的妖魔是什么厂抽? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任需频,我火速辦了婚禮,結(jié)果婚禮上筷凤,老公的妹妹穿的比我還像新娘昭殉。我一直安慰自己,他們只是感情好藐守,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布饲化。 她就那樣靜靜地躺著,像睡著了一般吗伤。 火紅的嫁衣襯著肌膚如雪吃靠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天足淆,我揣著相機與錄音巢块,去河邊找鬼。 笑死巧号,一個胖子當(dāng)著我的面吹牛族奢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丹鸿,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼越走,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了靠欢?” 一聲冷哼從身側(cè)響起廊敌,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎门怪,沒想到半個月后骡澈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡掷空,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年肋殴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坦弟。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡护锤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酿傍,到底是詐尸還是另有隱情烙懦,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布拧粪,位于F島的核電站修陡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏可霎。R本人自食惡果不足惜魄鸦,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望癣朗。 院中可真熱鬧拾因,春花似錦、人聲如沸旷余。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽正卧。三九已至蠢熄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炉旷,已是汗流浹背签孔。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窘行,地道東北人饥追。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像罐盔,于是被迫代替她去往敵國和親但绕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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