一、JSON解析方案
实际上:HttpMessageConverter起作用 功能:
服务端返回的对象序列化成json字符串 将前端传入的json字符串反序列化成java对象
jackson
pom.xml(web下自带了json)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
对日期进行格式化
第一种方法:@JsonFormat(Pattern=“yyyy-MM-dd”)
public class User {
private Integer id
;
private String name
;
private String address
;
private Date birthday
;
}
第二种方法:MappingJackson2HttpMessageConverter 注:若是需要设置编码的格式,还是需要该方式
@Bean
MappingJackson2HttpMessageConverter
mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter
= new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper
= new ObjectMapper();
SimpleDateFormat dateFormat
= new SimpleDateFormat("yyyy/MM/dd");
objectMapper
.setDateFormat(dateFormat
);
converter
.setObjectMapper(objectMapper
);
return converter
;
}
第三种方法:ObjectMapper
@Bean
ObjectMapper
objectMapper() {
ObjectMapper objectMapper
= new ObjectMapper();
objectMapper
.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
return objectMapper
;
}
gson
pom.xml 注:需要先把web中的json去除
<dependency>
<groupId>org
.springframework
.boot
</groupId
>
<artifactId>spring
-boot
-starter
-web
</artifactId
>
<exclusions>
<exclusion>
<groupId>org
.springframework
.boot
</groupId
>
<artifactId>spring
-boot
-starter
-json
</artifactId
>
</exclusion
>
</exclusions
>
</dependency
>
<!-- 导入gson依赖,不需要版本号,因为spring
-boot
-dependencies中导入了版本号
-->
<dependency>
<groupId>com
.google
.code
.gson
</groupId
>
<artifactId>gson
</artifactId
>
</dependency
>
时间格式化 第一种方法
@Bean
GsonHttpMessageConverter
gsonHttpMessageConverter() {
GsonHttpMessageConverter converter
= new GsonHttpMessageConverter();
converter
.setGson(new GsonBuilder().setDateFormat("yyyy-MM-dd").create());
return converter
;
}
第二种方法
@Bean
Gson
gson() {
return new GsonBuilder().setDateFormat("yyyy/MM/dd").create();
}
fastjson
pom.xml
<dependency>
<groupId>org
.springframework
.boot
</groupId
>
<artifactId>spring
-boot
-starter
-web
</artifactId
>
<exclusions>
<exclusion>
<groupId>org
.springframework
.boot
</groupId
>
<artifactId>spring
-boot
-starter
-json
</artifactId
>
</exclusion
>
</exclusions
>
</dependency
>
<!--导入fastjson依赖
-->
<dependency>
<groupId>com
.alibaba
</groupId
>
<artifactId>fastjson
</artifactId
>
<version>1.2.49</version
>
</dependency
>
FastJsonHttpMessageConverter(必须定义)
@Configuration
public class WebMvcConfig {
@Bean
FastJsonHttpMessageConverter
fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter converter
= new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig
= new FastJsonConfig();
fastJsonConfig
.setDateFormat("yyyy-MM-dd");
converter
.setFastJsonConfig(fastJsonConfig
);
return converter
;
}
}
二、静态资源访问
自定义静态文件位置
配置文件
#第一种方式:采用配置文件的方式
#源码在WebMvcAutoConfiguration
.class
#自定义静态资源的位置。默认五个
:"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/","/"(最后一个
/代表在webapp下
)
spring
.resources
.static-locations
=classpath
:/lyl
/
#静态资源中的内容将采用
/hello
java代码
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry
) {
registry
.addResourceHandler("/hello/**").addResourceLocations("classpath:/lyl/");
}
}
三、文件上传
单文件上传
@RestController
public class FileUploadController {
@PostMapping("/upload")
public String
upload(MultipartFile file
, HttpServletRequest request
) {
SimpleDateFormat simpleDateFormat
= new SimpleDateFormat("/yyyy-MM-dd/");
String originalFilename
= file
.getOriginalFilename();
String filename
= UUID
.randomUUID().toString() + originalFilename
.substring(originalFilename
.lastIndexOf("."));
String dateFormat
= simpleDateFormat
.format(new Date());
String filePath
= request
.getServletContext().getRealPath("/img") + dateFormat
;
File folder
= new File(filePath
);
if(!folder
.exists()) {
folder
.mkdirs();
}
try {
file
.transferTo(new File(folder
,filename
));
String url
= request
.getScheme() + "://" + request
.getServerName() + ":" + request
.getServerPort() + "/img" + dateFormat
+ filename
;
return url
;
} catch (IOException e
) {
e
.printStackTrace();
}
return "error";
}
!application
.properties
#单个文件上传大小。MB需要大写
spring
.servlet
.multipart
.max
-file
-size
=1MB
!表单的方式:
static/index
.html
<!--静态资源存放的五个位置可以直接访问文件名。因为制定了
addResourceHandle("/**")。
访问:localhost
:8080/index
.html
注:表单必须为post请求、enctype
="multipart/form-data"、输入框的type为file、name必须与控制器的形参对应。
-->
<form action
="/upload" method
="post" enctype
="multipart/form-data">
<input type
="file" name
="file">
<input type
="submit" value
="提交">
</form
>
!ajax的方式
<head>
<meta charset
="UTF-8">
<title>ajax进行文件上传
</title
>
<script src
="jquery-3.5.1.js"></script
>
</head
>
<body>
<div id
="result"></div
>
<input type
="file" id
="file">
<input type
="button" value
="上传" onclick
="upload()">
<script>
function
upload() {
var file
= $
("#file")[0].files
[0];
var formData
= new FormData();
formData
.append("file",file
);
//processData
:默认是
true。是否将上传的数据处理为对象
//contentType
:设置请求头。该处
false:是避免让jquery去设置请求头,因为会破坏分隔符(用来确认上传文件的起始位置)
$
.ajax({
type
:'post',
url
:"/upload",
processData
: false,
contentType
:false,
data
: formData
,
success
:function(msg
) {
$
('#result').html(msg
);
}
})
}
</script
>
</body
>
多文件上传
@PostMapping("/uploads")
public String
uploadS(MultipartFile
[] files
, HttpServletRequest request
) {
SimpleDateFormat simpleDateFormat
= new SimpleDateFormat("/yyyy-MM-dd/");
String dateFormat
= simpleDateFormat
.format(new Date());
String filePath
= request
.getServletContext().getRealPath("/img") + dateFormat
;
File folder
= new File(filePath
);
if(!folder
.exists()) {
folder
.mkdirs();
}
for (MultipartFile file
: files
) {
String originalFilename
= file
.getOriginalFilename();
String filename
= UUID
.randomUUID().toString() + originalFilename
.substring(originalFilename
.lastIndexOf("."));
try {
file
.transferTo(new File(folder
,filename
));
String url
= request
.getScheme() + "://" + request
.getServerName() + ":" + request
.getServerPort() + "/img" + dateFormat
+ filename
;
System
.out
.println(url
);
} catch (IOException e
) {
e
.printStackTrace();
}
}
return "success";
}
!多个input
<form action
="/uploads" method
="post" enctype
="multipart/form-data">s
<!-- name的属性要与
/uploads对应的那个控制器的形参一致
-->
<input type
="file" name
="files"><br>
<input type
="file" name
="files"><br>
<input type
="submit" value
="提交">
</form
>
!一个input上传多个文件
<form action
="/uploads" method
="post" enctype
="multipart/form-data">
<input type
="file" name
="files" multiple
>
<input type
="submit" value
="提交">
</form
>
四、@ControllerAdvice
处理全局异常
自定义全局异常
@ControllerAdvice
public class MyException {
@ExceptionHandler(MaxUploadSizeExceededException
.class)
public ModelAndView
exception(MaxUploadSizeExceededException m
) throws IOException
{
ModelAndView modelAndView
= new ModelAndView("MyError");
modelAndView
.addObject("error","上传文件大小超出限制");
return modelAndView
;
}
}
---classpath
:/templates
/MyError
.html
<!DOCTYPE html
>
<html lang
="en" xmlns
:th
="http://www.thymeleaf.org">
<head>
<meta charset
="UTF-8">
<title>Title
</title
>
</head
>
<body>
<h1 th
:text
="${error}"></h1
>
</body
>
</html
>
预设全局数据
GlobalData .java
@ControllerAdvice
public class GlobalData {
@ModelAttribute(value
= "info")
public Map
<String,Object> myData() {
Map
<String, Object> maps
= new HashMap<>();
maps
.put("name","蘑菇");
maps
.put("address","重庆");
return maps
;
}
HelloController
@RestController
public class HelloController {
@GetMapping("/hello")
public String
hello(Model model
) {
Map
<String, Object> map
= model
.asMap();
Set
<String> set
= map
.keySet();
for (String string
: set
) {
System
.out
.println(string
+ ":" + map
.get(string
));
}
return "hello";
}
}
请求参数预处理
GlobalData
@ControllerAdvice
public class GlobalData {
@InitBinder("a")
public void initA(WebDataBinder binder
) {
binder
.setFieldDefaultPrefix("a.");
}
@InitBinder("b")
public void initB(WebDataBinder binder
) {
binder
.setFieldDefaultPrefix("b.");
}
}
BookController
@PostMapping("/book")
public void book(@ModelAttribute("b") Book book
, @ModelAttribute("a") Author author
) {
System
.out
.println(book
);
System
.out
.println(author
);
}
测试时:输入b
.name
,b
.price
a
.name
,a
.age
五、异常数据处理
自定义错误页
查看错误页面的规则(优先级):先动态后静态,先精确(404)后模糊(4xx)在静态/动态页面下,新建【error/状态码.html】,项目运行出现问题时会自动调用对应的html
自定义异常数据
MyDefaultAttribute
@Component
public class MyDefaultAttribute extends DefaultErrorAttributes {
@Override
public Map
<String, Object> getErrorAttributes(WebRequest webRequest
, boolean includeStackTrace
) {
Map
<String, Object> map
= super.getErrorAttributes(webRequest
, includeStackTrace
);
map
.put("myError","自定义异常处理数据");
return map
;
}
}
classpath:resources/error/500.html
<!DOCTYPE html
>
<html lang
="en" xmlns
:th
="http://www.thymeleaf.org">
<head>
<meta charset
="UTF-8">
<title>500</title
>
</head
>
<body>
<table border
="1">
<tr>
<td>path
</td
>
<td th
:text
="${path}"></td
>
</tr
>
<tr>
<td>timestamp
</td
>
<td th
:text
="${timestamp}"></td
>
</tr
>
<tr>
<td>status
</td
>
<td th
:text
="${status}"></td
>
</tr
>
<tr>
<td>error
</td
>
<td th
:text
="${error}"></td
>
</tr
>
<tr>
<td>message
</td
>
<td th
:text
="${message}"></td
>
</tr
>
<tr>
<td>myError
</td
>
<td th
:text
="${myError}"></td
>
</tr
>
</table
>
<h1>500</h1
>
</body
>
</html
>
自定义异常视图
MyErrorViewResolver
@Component
public class MyErrorViewResolver extends DefaultErrorViewResolver {
public MyErrorViewResolver(ApplicationContext applicationContext
, ResourceProperties resourceProperties
) {
super(applicationContext
, resourceProperties
);
}
@Override
public ModelAndView
resolveErrorView(HttpServletRequest request
, HttpStatus status
, Map
<String, Object> model
) {
ModelAndView mv
= new ModelAndView();
mv
.setViewName("lyl");
mv
.addAllObjects(model
);
return mv
;
}
}
classpath:resources/error/lyl.html
<!DOCTYPE html
>
<html lang
="en" xmlns
:th
="http://www.thymeleaf.org">
<head>
<meta charset
="UTF-8">
<title>自定义异常视图
</title
>
</head
>
<body>
<h1>自定义异常视图
</h1
>
<table border
="1">
<tr>
<td>path
</td
>
<td th
:text
="${path}"></td
>
</tr
>
<tr>
<td>timestamp
</td
>
<td th
:text
="${timestamp}"></td
>
</tr
>
<tr>
<td>status
</td
>
<td th
:text
="${status}"></td
>
</tr
>
<tr>
<td>error
</td
>
<td th
:text
="${error}"></td
>
</tr
>
<tr>
<td>message
</td
>
<td th
:text
="${message}"></td
>
</tr
>
<tr>
<td>myError
</td
>
<td th
:text
="${myError}"></td
>
</tr
>
</table
>
<h1>lyl
</h1
>
</body
>
</html
>
六、Cors
第一种方法
@RestController
public class HelloController {
@GetMapping("/get")
public String
get() {
return "hello get";
}
@PutMapping("/put")
public String
put() {
return "hello put";
}
}
第二种方法
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry
) {
registry
.addMapping("/**").allowedOrigins("http://localhost:8081")
.allowedHeaders("*")
.allowedMethods("*")
.maxAge(30*1000);
}
}
Cors2访问Cors1
<!DOCTYPE html
>
<html lang
="en">
<head>
<meta charset
="UTF-8">
<title>Cors
</title
>
<script src
="jquery-3.5.1.js"></script
>
</head
>
<body>
<div id
="app"></div
>
<input type
="button" value
="GET" onclick
="getData()">
<input type
="button" value
="PUT" onclick
="putData()">
<script>
function
getData() {
$
.get("http://localhost:8080/get",function(msg
) {
$
('#app').html(msg
);
});
}
function
putData() {
$
.ajax({
type
:'put',
url
:"http://localhost:8080/put",
success
:function(msg
) {
$
('#app').html(msg
)
}
})
}
</script
>
</body
>
</html
>
六、拦截器
MyInterceptor
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request
, HttpServletResponse response
, Object handler
) throws Exception
{
System
.out
.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request
, HttpServletResponse response
, Object handler
, ModelAndView modelAndView
) throws Exception
{
System
.out
.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request
, HttpServletResponse response
, Object handler
, Exception ex
) throws Exception
{
System
.out
.println("afterCompletion");
}
}
WebMvcConfig
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry
) {
registry
.addInterceptor(myInterceptor()).addPathPatterns("/**");
}
@Bean
MyInterceptor
myInterceptor() {
return new MyInterceptor();
}
}