1. 返回json数据
默认实现
2. 自定义转换器
1.使用Gson
先导入依赖
springboot默认提供了Gson的自动转换类 GsonHttpMessageConvertersConfiguration。所以Gson添加成功之后,可以像使用jackson-databind一样直接使用Gson。但是这里不支持对日期数据格式化。
如果想日期数据格式化,需要自定义HttpMessageConverter
不格式化
格式化
@Configuration
public class GsonConfig {
@Bean // 自己提供一个GsonHttpMessageConverter实例
GsonHttpMessageConverter gsonHttpMessageConverter() {
GsonHttpMessageConverter convert = new GsonHttpMessageConverter();
GsonBuilder builder = new GsonBuilder();
// 设置Gson解析时日期的格式
builder.setDateFormat("yyyy-MM-dd");
// 设置Gson解析时修饰符为protected的字段被过滤掉
builder.excludeFieldsWithModifiers(Modifier.PROTECTED);
// 创建Gson对象放入GsonHttpMessageConverter实例中并返回convert
Gson gson = builder.create();
convert.setGson(gson);
return convert;
}
}
2. 使用json
配置1
@Configuration
public class MyFastJsonConfig {
@Bean
FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setDateFormat("yyyy-MM-dd");
config.setCharset(Charset.forName("utf-8"));
config.setSerializerFeatures(
SerializerFeature.WriteClassName,
SerializerFeature.WriteMapNullValue,
SerializerFeature.PrettyFormat,
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteNullStringAsEmpty);
converter.setFastJsonConfig(config);
return converter;
}
}
MyFastJsonConfig配置完成后,还有配置一下响应编码,否则返回json会出现中文乱码。
配置2
除了上述配置,还有一种配置方法,就是继承WebMVCAutoConfiguration,然后重写里面的特定方法
3. 静态资源目录及其优先级
优先级:即先去找 /META-INF/resources下的p1,找不到去找resources下的
4. 文件上传
总结,一共有2个文件上传组件
CommonsMultipartResolver 使用commons-fileupload来初始multipart请求
StandardServletMultipartResolver使用Servlet3.0来处理。
springboot默认使用第二个。
相关配置
5. @ControllerAdvice:全局数据、异常、请求参数处理
5.1、全局异常处理 @ControllerAdvice + @ExceptionHandler
@ControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public void arithException(ArithmeticException e, HttpServletResponse resp) throws IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("运算异常!");
out.flush();
out.close();
}
@ExceptionHandler(NullPointerException.class)
public ModelAndView arithException2(NullPointerException e) {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","空指针异常!");
mv.setViewName("error");
// mv.setViewName("handle");
return mv;
}
}
control层
@RequestMapping("/exception")
public int testExe() {
int c = 20/0;
return c;
}
@RequestMapping("/exception2")
public String[] testExe2() {
String[] arr = new String[2];
String[] split = arr[1].split(",");
return split;
}
5.2、添加全局数据 @ControllerAdvice + @ModelAttribute
5.3、请求参数处理 @ControllerAdvice+@ModelAttribute+@InitBinder
来看一种情况
(其实这里参数user、author前隐含了 @ModelAttribute)
怎么解决这种情况呢?
如上,问题得以解决。
解释一下上面的代码。上面的@ModelAttribute把对象a和对象b封装到了model里。然后在全局配置页面上,有InitBinder 为model里a和b对象做了一些改动,即给对象的所有的属性字段增加了 前缀。这样就能区分出name了。
在WebDataBinder对象中,还可以设置允许的字段、禁止的字段、必填字段以及验证器等。
6. CORS支持
6.1、什么是跨域?
如果一个服务是91端口,这个服务又调用其他的服务。而这个服务是90端口,这就会出现跨域
6.2、跨域怎么解决?
1、jsonp,
缺点:只支持Get,而且是把远程的函数拉过来本地运行。和开发流程不符合。所以最好使用CROS
2、CROS
比如:
对8080:当前服务是在8080端口,而我的前端想访问8081端口里的服务(添加、删除),请求8081
对8081:如果8081端口的服务里这两个方法没有开启跨域支持8080,那么就会访问失败(没有解决跨域)
总结,当8080端口的前端页面需要去8081端口拿数据(而不是8080自身),就会出现跨域。解决办法是让8081端口允许被跨域。
注意:跨域指的不是自身前端页面解决,而是被请求的后端资源去解决。被请求的服务要允许自己被其他人访问,而不是仅仅是自身才能访问。
服务端支持跨域
完整的跨域流程
跨域解决
有两种办法:一种在方法上加@CrossOrigin、一种在全局进行配置
下面创建两个工程
8081工程提供后端服务。这里配置跨域,表示自己的资源可以被跨域取到。
8080工程负责前端请求。这里发起ajax请求,去拿8081端口的服务。
8081工程:这里是写在了方法上。
@RestController
@RequestMapping("/book")
public class CROSController {
@PostMapping("/")
@CrossOrigin(value="http://localhost:8080",maxAge = 1800,allowedHeaders = "*")
public String addBook(String name) {
return "receive:"+name;
}
@DeleteMapping("/{id}")
@CrossOrigin(value="http://localhost:8080",maxAge = 1800,allowedHeaders = "*")
public String deleteById(@PathVariable Long id) {
return String.valueOf(id);
}
}
还可以写在全局中
@Configuration
public class MyWebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/book/**")
.allowedHeaders("*")
.allowedMethods("*")
.maxAge(1800)
.allowedOrigins("http://localhost:8080");
}
}
配置文件把端口改成8081
8080工程:
resources/static文件下创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js">
</script>
</head>
<body>
<div id="contentDiv"></div>
<div id="deleteResult"></div>
<input type="button" value="提交数据" onclick="getData()"><br>
<input type="button" value="删除数据" onclick="deleteData()"><br>
<script>
function deleteData() {
$.ajax({
url: 'http://localhost:8081/book/99',
type: 'delete',
success: function(msg) {
$("#deleteResult").html(msg);
}
})
}
function getData() {
$.ajax({
url: 'http://localhost:8081/book/',
type: 'post',
data: {name: '三国演义'},
success: function(msg) {
$("#contentDiv").html(msg);
}
})
}
</script>
</body>
</html>
然后运行两个服务。运行结果如下:
如果我把跨域代码注释,运行结果变成了:
7. 配置类与xml配置
springboot一般建议写成配置类的形式来取代xml配置文件。
如果实在想用xml文件,也可以通过@ImportResource进行导入。
比如我创建了一个bean.xml,里面注册了一个组件hello。
然后我想引入,此时我可以创建一个Beans配置类。
8. 注册拦截器
这里具体怎么创建的,已经用过很多次了,不再介绍了。下面给出一些注意事项。
9. 启动系统任务
9.1 CommandLineRunner
代码:
Order可以看成前后,而不是大小,1,2,3都是序号,序号越靠前的越先执行。
运行结果:
在idea启动器上加上参数:三国演义 罗贯中,然后运行,看看控制台
9.2 ApplicationRunner
10. 整合Servlet、Filter和Listener
11. 路径映射
12. 配置AOP
如果想给某个包下所有类、某个类、类中的某个方法配置切面。
创建切面类,通过切入点指定你想切入的地方。
配置各种通知。
然后通过@Component注册到容器里。然后直接就可以使用了