4-springboot知识点(1)-json解析方案(jackson、gson、fastjson)、静态资源访问、文件上传、@ControllerAdvice、异常数据处理、Cors、拦截器

    技术2026-08-31  30

    一、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; //第一种方式:json日期格式化。该方法只在jackson中有效 //弊端:要在每个实体类日期属性上加 //@JsonFormat(pattern = "yyyy-MM-dd") private Date birthday; } 第二种方法:MappingJackson2HttpMessageConverter 注:若是需要设置编码的格式,还是需要该方式 @Bean MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); ObjectMapper objectMapper = new ObjectMapper(); //第二种方式:对日期进行格式化(源码在JacksonHttpMessageConvertersConfiguration中的MappingJackson2HttpMessageConverter) //原则上是ObjectMapping在起作用 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> 时间格式化 第一种方法 //第一种方式:源码在GsonHttpMessageConvertersConfiguration.class中的GsonHttpMessageConverter @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 { //fastjson:必须要自定义一个FastJsonHttpMessageConverter @Bean FastJsonHttpMessageConverter fastJsonHttpMessageConverter() { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); //设置编码格式 /* List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); converter.setSupportedMediaTypes(fastMediaTypes);*/ 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/**(具体文件)进行访问。默认是/** spring.mvc.static-path-pattern=/hello/** java代码 @Configuration public class WebMvcConfig implements WebMvcConfigurer { //第二种:采用java的方式进行静态资源的访问 @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/hello/**").addResourceLocations("classpath:/lyl/"); } }

    三、文件上传

    单文件上传 @RestController public class FileUploadController { //上传文件需要注意: //1.上传的文件需要分类,不然文件过多,会导致加载很慢 //2.文件上传要限制大小 //3.重新命名文件名 @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()); //request.getServletContext().getRealPath("/img"):返回的是一个临时文件的路径 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> //引入jquery <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> 多文件上传 /** * 多文件上传 * 情况:1.多个input。2.一个input上传多个文件 * @param files * @param request * @return */ @PostMapping("/uploads") public String uploadS(MultipartFile[] files, HttpServletRequest request) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("/yyyy-MM-dd/"); //存取文件的位置. String dateFormat = simpleDateFormat.format(new Date()); //request.getServletContext().getRealPath("/img"):返回的是一个临时文件的路径 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 void exception(MaxUploadSizeExceededException m, HttpServletResponse response) throws IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.write("上传文件大小超出限制"); out.flush(); out.close(); }*/ //使用静态页面进行错误输出 //thymeleaf模板默认是在templates下 @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 { //@ControllerAdvice第二种用法:预设全局数据 //在当前项目的任何一个controller中都能获取得到 //获取到的是一个map,其中key为info,value为maps @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) { //获取到GlobalData中的数据 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 { //@ControllerAdvice第三种用法:请求参数预处理 //@InitBinder的内容与@ModelAttribute()的内容对应 @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 ,则源码ErrorMvcAutoConfiguration中的DefaultErrorAttribute就会失效。 @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); } //自定义结果视图 //Map<String, Object> model:是一个不可修改的map @Override public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) { ModelAndView mv = new ModelAndView(); //lyl.html需要放在templates下面 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 { //第一种方式 //允许cors2(端口8081)进行访问. //@CrossOrigin:可以放在方法和类上. //缺点:多个controller要写多次 //愿意接收来自http://localhost:8081的请求 //@CrossOrigin(origins = "http://localhost:8081") @GetMapping("/get") public String get() { return "hello get"; } @PutMapping("/put") public String put() { return "hello put"; } } 第二种方法 @Configuration public class WebMvcConfig implements WebMvcConfigurer { /** * 配置跨域请求 * @param registry */ @Override public void addCorsMappings(CorsRegistry registry) { //第二种方式:仅需设置一次 //addMapping:哪些接口允许跨域 //maxAge:有效时间(例:如果发送的请求是PUT请求,那么会发送两次,第一次发送PUT,是一个探测请求,发送到服务器判断是否支持PUT请求 // ,存在就发送第二次请求。maxAge代表的是探测请求的有效时间,在有效时间内,就不用发送探测请求了。 // ) 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 :以下两个方法才能执行 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) { //addPathPatterns:需要拦截的 registry.addInterceptor(myInterceptor()).addPathPatterns("/**"); } @Bean MyInterceptor myInterceptor() { return new MyInterceptor(); } }
    Processed: 0.009, SQL: 9