1. 返回json数据

默认实现

image.pngimage.png

2. 自定义转换器

1.使用Gson

先导入依赖
image.png
image.png
springboot默认提供了Gson的自动转换类 GsonHttpMessageConvertersConfiguration。所以Gson添加成功之后,可以像使用jackson-databind一样直接使用Gson。但是这里不支持对日期数据格式化。
如果想日期数据格式化,需要自定义HttpMessageConverter

不格式化
image.pngimage.png

格式化

  1. @Configuration
  2. public class GsonConfig {
  3. @Bean // 自己提供一个GsonHttpMessageConverter实例
  4. GsonHttpMessageConverter gsonHttpMessageConverter() {
  5. GsonHttpMessageConverter convert = new GsonHttpMessageConverter();
  6. GsonBuilder builder = new GsonBuilder();
  7. // 设置Gson解析时日期的格式
  8. builder.setDateFormat("yyyy-MM-dd");
  9. // 设置Gson解析时修饰符为protected的字段被过滤掉
  10. builder.excludeFieldsWithModifiers(Modifier.PROTECTED);
  11. // 创建Gson对象放入GsonHttpMessageConverter实例中并返回convert
  12. Gson gson = builder.create();
  13. convert.setGson(gson);
  14. return convert;
  15. }
  16. }

image.png

2. 使用json

配置1
  1. @Configuration
  2. public class MyFastJsonConfig {
  3. @Bean
  4. FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
  5. FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
  6. FastJsonConfig config = new FastJsonConfig();
  7. config.setDateFormat("yyyy-MM-dd");
  8. config.setCharset(Charset.forName("utf-8"));
  9. config.setSerializerFeatures(
  10. SerializerFeature.WriteClassName,
  11. SerializerFeature.WriteMapNullValue,
  12. SerializerFeature.PrettyFormat,
  13. SerializerFeature.WriteNullListAsEmpty,
  14. SerializerFeature.WriteNullStringAsEmpty);
  15. converter.setFastJsonConfig(config);
  16. return converter;
  17. }
  18. }

image.png
MyFastJsonConfig配置完成后,还有配置一下响应编码,否则返回json会出现中文乱码。
image.png

配置2

除了上述配置,还有一种配置方法,就是继承WebMVCAutoConfiguration,然后重写里面的特定方法
image.png

3. 静态资源目录及其优先级

image.png
image.png
优先级:即先去找 /META-INF/resources下的p1,找不到去找resources下的

4. 文件上传

image.pngimage.png
总结,一共有2个文件上传组件
CommonsMultipartResolver 使用commons-fileupload来初始multipart请求
StandardServletMultipartResolver使用Servlet3.0来处理。
springboot默认使用第二个。

相关配置

image.png

5. @ControllerAdvice:全局数据、异常、请求参数处理

5.1、全局异常处理 @ControllerAdvice + @ExceptionHandler

  1. @ControllerAdvice
  2. public class CustomExceptionHandler {
  3. @ExceptionHandler(ArithmeticException.class)
  4. public void arithException(ArithmeticException e, HttpServletResponse resp) throws IOException {
  5. resp.setContentType("text/html;charset=utf-8");
  6. PrintWriter out = resp.getWriter();
  7. out.write("运算异常!");
  8. out.flush();
  9. out.close();
  10. }
  11. @ExceptionHandler(NullPointerException.class)
  12. public ModelAndView arithException2(NullPointerException e) {
  13. ModelAndView mv = new ModelAndView();
  14. mv.addObject("msg","空指针异常!");
  15. mv.setViewName("error");
  16. // mv.setViewName("handle");
  17. return mv;
  18. }
  19. }

control层

  1. @RequestMapping("/exception")
  2. public int testExe() {
  3. int c = 20/0;
  4. return c;
  5. }
  6. @RequestMapping("/exception2")
  7. public String[] testExe2() {
  8. String[] arr = new String[2];
  9. String[] split = arr[1].split(",");
  10. return split;
  11. }

image.pngimage.png

5.2、添加全局数据 @ControllerAdvice + @ModelAttribute

image.png

5.3、请求参数处理 @ControllerAdvice+@ModelAttribute+@InitBinder

来看一种情况
image.pngimage.png
image.png
(其实这里参数user、author前隐含了 @ModelAttribute)
image.png

怎么解决这种情况呢?
image.pngimage.pngimage.png
如上,问题得以解决。
解释一下上面的代码。上面的@ModelAttribute把对象a和对象b封装到了model里。然后在全局配置页面上,有InitBinder 为model里a和b对象做了一些改动,即给对象的所有的属性字段增加了 前缀。这样就能区分出name了。
在WebDataBinder对象中,还可以设置允许的字段、禁止的字段、必填字段以及验证器等。

6. CORS支持

6.1、什么是跨域?

image.pngimage.pngimage.png
image.pngimage.png
如果一个服务是91端口,这个服务又调用其他的服务。而这个服务是90端口,这就会出现跨域
image.pngimage.png

6.2、跨域怎么解决?

1、jsonp,

缺点:只支持Get,而且是把远程的函数拉过来本地运行。和开发流程不符合。所以最好使用CROS
image.png

2、CROS

比如:
对8080:当前服务是在8080端口,而我的前端想访问8081端口里的服务(添加、删除),请求8081
对8081:如果8081端口的服务里这两个方法没有开启跨域支持8080,那么就会访问失败(没有解决跨域)
总结,当8080端口的前端页面需要去8081端口拿数据(而不是8080自身),就会出现跨域。解决办法是让8081端口允许被跨域。
注意:跨域指的不是自身前端页面解决,而是被请求的后端资源去解决。被请求的服务要允许自己被其他人访问,而不是仅仅是自身才能访问。

服务端支持跨域

image.png

完整的跨域流程

image.pngimage.pngimage.png

跨域解决

有两种办法:一种在方法上加@CrossOrigin、一种在全局进行配置
下面创建两个工程
8081工程提供后端服务。这里配置跨域,表示自己的资源可以被跨域取到。
8080工程负责前端请求。这里发起ajax请求,去拿8081端口的服务。

8081工程:这里是写在了方法上。

  1. @RestController
  2. @RequestMapping("/book")
  3. public class CROSController {
  4. @PostMapping("/")
  5. @CrossOrigin(value="http://localhost:8080",maxAge = 1800,allowedHeaders = "*")
  6. public String addBook(String name) {
  7. return "receive:"+name;
  8. }
  9. @DeleteMapping("/{id}")
  10. @CrossOrigin(value="http://localhost:8080",maxAge = 1800,allowedHeaders = "*")
  11. public String deleteById(@PathVariable Long id) {
  12. return String.valueOf(id);
  13. }
  14. }

image.pngimage.png
还可以写在全局中

  1. @Configuration
  2. public class MyWebConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addCorsMappings(CorsRegistry registry) {
  5. registry.addMapping("/book/**")
  6. .allowedHeaders("*")
  7. .allowedMethods("*")
  8. .maxAge(1800)
  9. .allowedOrigins("http://localhost:8080");
  10. }
  11. }

image.png
配置文件把端口改成8081

8080工程:
resources/static文件下创建index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js">
  7. </script>
  8. </head>
  9. <body>
  10. <div id="contentDiv"></div>
  11. <div id="deleteResult"></div>
  12. <input type="button" value="提交数据" onclick="getData()"><br>
  13. <input type="button" value="删除数据" onclick="deleteData()"><br>
  14. <script>
  15. function deleteData() {
  16. $.ajax({
  17. url: 'http://localhost:8081/book/99',
  18. type: 'delete',
  19. success: function(msg) {
  20. $("#deleteResult").html(msg);
  21. }
  22. })
  23. }
  24. function getData() {
  25. $.ajax({
  26. url: 'http://localhost:8081/book/',
  27. type: 'post',
  28. data: {name: '三国演义'},
  29. success: function(msg) {
  30. $("#contentDiv").html(msg);
  31. }
  32. })
  33. }
  34. </script>
  35. </body>
  36. </html>

然后运行两个服务。运行结果如下:
image.png
如果我把跨域代码注释,运行结果变成了:
image.png

7. 配置类与xml配置

springboot一般建议写成配置类的形式来取代xml配置文件。
如果实在想用xml文件,也可以通过@ImportResource进行导入。
比如我创建了一个bean.xml,里面注册了一个组件hello。
然后我想引入,此时我可以创建一个Beans配置类。
image.png

8. 注册拦截器

这里具体怎么创建的,已经用过很多次了,不再介绍了。下面给出一些注意事项。
image.png

9. 启动系统任务

image.png

9.1 CommandLineRunner

代码:

image.png
Order可以看成前后,而不是大小,1,2,3都是序号,序号越靠前的越先执行。

运行结果:

在idea启动器上加上参数:三国演义 罗贯中,然后运行,看看控制台
image.pngimage.png

9.2 ApplicationRunner

image.pngimage.pngimage.pngimage.pngimage.png

10. 整合Servlet、Filter和Listener

image.pngimage.pngimage.pngimage.png

11. 路径映射

image.png

12. 配置AOP

如果想给某个包下所有类、某个类、类中的某个方法配置切面。
创建切面类,通过切入点指定你想切入的地方。
配置各种通知。
然后通过@Component注册到容器里。然后直接就可以使用了
image.pngimage.pngimage.png

13. 放弃某些自动配置类

image.pngimage.png