SpringMVC配置(三)
发表于更新于
字数总计:3.2k阅读时长:14分钟阅读量: 成都
Spring-MVC入门配置
REST风格
REST介绍
一种比较好的url风格
没有使用REST
- /user/findById?id=1 查找用户
- /user/deleteById?id=1 删除用户
使用了REST
/user/1 get 查找用户
/user/1 delete 删除用户
/user post 保存用户
/user put 更新用户
也是使用url+方法的方式来区分url的功能
SpringMVC中的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package org.example.controller;
import org.example.domain.JsonResult; import org.example.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;
@Controller public class UserController { @RequestMapping(value = "/user", method = RequestMethod.POST) @ResponseBody public JsonResult save(@RequestBody User user) { return new JsonResult(200, "保存成功!", user); }
@RequestMapping(value = "/user", method = RequestMethod.PUT) @ResponseBody public JsonResult update(@RequestBody User user) { return new JsonResult(200, "更新成功!", user); }
@RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE) @ResponseBody public JsonResult deleteById(@PathVariable Integer id) { return new JsonResult(200, id + "删除成功!", null); }
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET) @ResponseBody public JsonResult findById(@PathVariable Integer id) { return new JsonResult(200, id + "查找成功!", new User()); } }
|
简化
通过上面的代码发现有很多重复的地方,写起来非常繁琐,可以简化为如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package org.example.controller;
import org.example.domain.JsonResult; import org.example.domain.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*;
@Controller
@ResponseBody
@RequestMapping("/user") public class UserController { @PostMapping public JsonResult save(@RequestBody User user) { return new JsonResult(200, "保存成功!", user); }
@PutMapping public JsonResult update(@RequestBody User user) { return new JsonResult(200, "更新成功!", user); }
@DeleteMapping("/{id}") public JsonResult deleteById(@PathVariable Integer id) { return new JsonResult(200, id + "删除成功!", null); }
@GetMapping("/{id}") @ResponseBody public JsonResult findById(@PathVariable Integer id) { return new JsonResult(200, id + "查找成功!", new User()); } }
|
其中@Controller
注解可以与@ResponseBody
注解融合成一个注解,即@RestController
,最终简化如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| package org.example.controller;
import org.example.domain.JsonResult; import org.example.domain.User; import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user") public class UserController { @PostMapping public JsonResult save(@RequestBody User user) { return new JsonResult(200, "保存成功!", user); }
@PutMapping public JsonResult update(@RequestBody User user) { return new JsonResult(200, "更新成功!", user); }
@DeleteMapping("/{id}") public JsonResult deleteById(@PathVariable Integer id) { return new JsonResult(200, id + "删除成功!", null); }
@GetMapping("/{id}") @ResponseBody public JsonResult findById(@PathVariable Integer id) { return new JsonResult(200, id + "查找成功!", new User()); } }
|
异常处理
简介
程序中会出现一系列的异常,我们不能保证能够捕获所有的异常,可以使用spring的aop为表现层的方法设置异常捕获切面
创建异常通知
创建org.example.controller.aop.ProjectExceptionAdvice异常通知类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package org.example.controller.aop;
import org.example.domain.JsonResult; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler(Exception.class) public JsonResult exceptionHandler(Exception exception) { return new JsonResult(500, exception.getMessage(), null); } }
|
重启服务将会开启全局异常处理
细分异常
通常我们会对不同层面的异常有不同的处理方案
例如如果因为用户的输入不正确导致的表现层异常那么我们就只需要提醒用户输入正确就行了
但是如果是系统异常,那么我们需要记录日志并且通知运维人员及时修复
如果是未知的系统异常,那么我们也需要记录日志并且通知程序员进行修复,如果不是程序员的错误,程序员只需要将此错误重新归类到系统异常或者业务异常就行了
创建业务异常
创建org.example.exception.BusinessException
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package org.example.exception;
public class BusinessException extends RuntimeException { private Integer code;
public BusinessException() { }
public BusinessException(Integer code) { this.code = code; }
public BusinessException(Integer code, String message) { super(message); this.code = code; }
public Integer getCode() { return code; }
public void setCode(Integer code) { this.code = code; } }
|
创建系统异常
创建org.example.exception.SystemException
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package org.example.exception;
public class SystemException extends RuntimeException { private Integer code;
public SystemException() { }
public SystemException(Integer code) { this.code = code; }
public SystemException(Integer code, String message) { super(message); this.code = code; }
public Integer getCode() { return code; }
public void setCode(Integer code) { this.code = code; } }
|
添加异常处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package org.example.controller.aop;
import org.example.domain.JsonResult; import org.example.exception.BusinessException; import org.example.exception.SystemException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice public class ProjectExceptionAdvice { @ExceptionHandler(SystemException.class) public JsonResult businessException(SystemException systemException) {
return new JsonResult(500, "系统繁忙,请稍后再试", null); }
@ExceptionHandler(BusinessException.class) public JsonResult businessException(BusinessException businessException) { return new JsonResult(400, "请不要使用违规操作", null); }
@ExceptionHandler(Exception.class) public JsonResult exceptionHandler(Exception exception) {
return new JsonResult(500, exception.getMessage(), null); } }
|
测试
写一个有异常的controller处理方法来进行测试
1 2 3 4 5 6 7 8
| @GetMapping("/test/exception/{id}") public JsonResult testException(@PathVariable Integer id) { if (id == 1) { throw new BusinessException(); } else { throw new SystemException(); } }
|
访问http://127.0.0.1/user/test/exception/1
,出现以下结果
1 2 3 4 5
| { "code": 400, "message": "请不要使用违规操作", "data": null }
|
访问http://127.0.0.1/user/test/exception/2
,出现以下结果
1 2 3 4 5
| { "code": 500, "message": "系统繁忙,请稍后再试", "data": null }
|
开放静态资源
创建支持类
创建org.example.config.SpringMvcSupport支持类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package org.example.config;
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration public class SpringMvcSupport extends WebMvcConfigurationSupport { @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**").addResourceLocations("/pages/"); } }
|
载入容器中
在org.example.config.SpringMvcConfig中添加扫描
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package org.example.config;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@ComponentScan({"org.example.controller", "org.example.config"})
@EnableWebMvc
public class SpringMvcConfig { }
|
在webapp文件夹下创建pages文件夹,在pages文件夹下创建一个index.html文件
访问http://127.0.0.1/pages/index.html
即可获取到页面
简化代码
不需要创建名为org.example.config.SpringMvcSupport的支持类,直接在org.example.config.SpringMvcConfig中进行支持的编写
删除org.example.config.SpringMvcSupport类,并修改org.example.config.SpringMvcConfig配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package org.example.config;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@ComponentScan({"org.example.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer { public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**").addResourceLocations("/pages/"); } }
|
访问http://127.0.0.1/pages/index.html
依然可行
拦截器
简介
拦截器与过滤器有很大的区别,过滤器是servlet的技术,范围较大
而拦截器是SpringMVC的技术,范围较小,而且与SpringMVC配合起来更加灵活
创建拦截器
创建org.example.controller.interceptor.ProjectInterceptor拦截器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package org.example.controller.interceptor;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@Component public class ProjectInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("preHandle"); return true; }
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); }
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); } }
|
更新Spring配置
因为之前使用了支持的简化方法,所以在SpringMvcConfig配置类中添加拦截器支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package org.example.config;
import org.example.controller.interceptor.ProjectInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@ComponentScan({"org.example.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer { @Autowired private ProjectInterceptor projectInterceptor;
public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/user","/user/**"); }
public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/pages/**").addResourceLocations("/pages/"); } }
|
配置完成,访问http://127.0.0.1/user
出现以下打印表示配置正确
1 2 3
| preHandle postHandle afterCompletion
|
多个拦截器配置
多个拦截器也是一样的步骤,先创建一个新的拦截器,然后再在Spring配置类中添加就行了,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Autowired private ProjectInterceptor projectInterceptor;
@Autowired private ProjectInterceptor2 projectInterceptor2;
public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(projectInterceptor).addPathPatterns("/user","/user/**"); registry.addInterceptor(projectInterceptor2).addPathPatterns("/user","/user/**"); }
|
拦截器中的参数
目前只列出了以下内容,还有更多的需要自己去探索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| package org.example.controller.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper; import org.example.domain.JsonResult; import org.example.domain.User; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter;
@Component public class ProjectInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String header = request.getHeader("Content-Type"); System.out.println(header);
HandlerMethod handlerMethod = (HandlerMethod) handler; System.out.println(handlerMethod.getBeanType()); handlerMethod.getMethod().invoke(handlerMethod.getBean(), new User());
if (request.getRequestURI().equals("/user")) { response.setHeader("Content-Type", "application/json"); PrintWriter writer = response.getWriter(); writer.write(new ObjectMapper().writeValueAsString(new JsonResult(200, "please login first", null))); writer.flush(); writer.close(); return false; } return true; }
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle"); }
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion"); } }
|