Spring MVC是
与Spring框架集成的实现了MVC设计模式的请求驱动类型的轻量级 Web框架
核心组件
- DispatcherServlet
前端控制器:接收请求、响应结果,起到转发器到作用,减少其它组件之间的耦合度。 - HandlerMapping
处理器映射器:URL与处理器的映射 - HandlerAdapter
处理器适配器 - Handler
处理器:业务逻辑在这里开发 - ViewResolver
视图解析器 - View
视图接口:有jsp,freemarker等不同的视图实现类
工作流程
Browser---[发起request]--->DispatcherServlet----[调用HandlerMapping]---->获取Handler(可能还有+ Handler Interceptor)----[返回给]---->DispatcherServlet----[调用 HandlerAdapter]---->调用Handler----[执行返回ModelAndView]---->HandlerAdapter----[返回ModelAndView]---->DispatcherServlet----[传递ModelAndView]---->ViewResolver解析----[返回View]---->DispatcherServlet渲染View----[返回Response]---->Browser
常用注解
- @Controller > @RestController所有方法自带@ResponseBody的@Controller
- @RequestMapping
三类六属性
- value:请求地址,URI Template模式; method:GET、POST、PUT、DELETE
- consumes:请求Content-Type;produces:响应Content-Type
- params:请求必须包含的参数;headers:请求必须包含的header
特化: @GetMapping @PostMapping @PutMapping @DeleteMapping
- @PathVariable @RequestParam @RequestBody
POST /user/{id}?a1=xxxx&a2=yyyy
{b: "bValue", c: "cValue"}
则: @PathVariable取id的实际值,@RequestParam 取a1,a2的实际值, @RequestBody取得请求体并转为指定对象 - @ResponseBody
响应数据
解决请求乱码
配置文件application.properties
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
server.tomcat.uri-encoding=UTF-8
解决响应乱码
@Configuration
public class CustomMVCConfiguration extends WebMvcConfigurerAdapter {
@Bean
public HttpMessageConverter<String> responseBodyConverter() {
StringHttpMessageConverter converter = new StringHttpMessageConverter(
Charset.forName("UTF-8"));
return converter;
}
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
converters.add(responseBodyConverter());
}
@Override
public void configureContentNegotiation(
ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}
————————————————
版权声明:本文为CSDN博主「wangshuang1631」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wangshuang1631/article/details/70753801
异常处理
- Spring管理的异常
BindException
400 - Bad Request
ConversionNotSupportedException
500 - Internal Server Error
HttpMediaTypeNotAcceptableException
406 - Not Acceptable
HttpMediaTypeNotSupportedException
415 - Unsupported Media Type
HttpMessageNotReadableException
400 - Bad Request
HttpMessageNotWritableException
500 - Internal Server Error
HttpRequestMethodNotSupportedException
405 - Method Not Allowed
MethodArgumentNotValidException
400 - Bad Request
MissingServletRequestParameterException
400 - Bad Request
MissingServletRequestPartException
400 - Bad Request
NoSuchRequestHandlingMethodException
404 - Not Found
TypeMismatchException
400 - Bad Request
作者:RebeccaZhong
链接:https://juejin.cn/post/6844903865674891278
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 自定义异常的自定义响应HTTP状态码
@ResponseStatus(value = HttpStatus.NO_CONTENT, reason = "No Content")
public class NullOrgException extends RuntimeException {
}
作者:RebeccaZhong
链接:https://juejin.cn/post/6844903865674891278
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- Controller级异常处理
@Controller
@RequestMapping("test/exception")
public class ExceptionTestController {
private Logger logger = LoggerFactory.getLogger(ExceptionTestController.class);
@Autowired
private OrgService service;
@RequestMapping(value = "orgs", method = RequestMethod.GET)
@ResponseBody
public List<Org> getOrgs () {
List<Org> orgs = service.getOrgs();
return orgs;
}
@ExceptionHandler(NullOrgException.class)
public String handleNullOrgException() {
return "无组织机构相关数据!";
}
}
作者:RebeccaZhong
链接:https://juejin.cn/post/6844903865674891278
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 全局异常处理
@ControllerAdvice // 定义控制器类
public class AppWideException {
// 定义异常处理方法
@ExceptionHandler(NullOrgException.class)
public String handleNullOrgException() {
return "无组织机构相关数据!";
}
}
作者:RebeccaZhong
链接:https://juejin.cn/post/6844903865674891278
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
跨域问题
- 根源
浏览器的同源策略 - 没有同源策略的危害
CSRF攻击 - 后端规避同源策略的方法
Controller级
@CrossOrigin(origins = "http://domain2.com", maxAge = 3600) // <<<---看这里
@RestController
@RequestMapping("/account")
public class AccountController {
@GetMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
@DeleteMapping("/{id}")
public void remove(@PathVariable Long id) {
// ...
}
}
或全局
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
};
}
}
拦截器
- 实现HandlerInterceptor接口
@Component
public class PasswordStateInterceptor implements HandlerInterceptor { // 必须实现HandlerInterceptor接口
@Autowired
private UserEncryptResetRepository userEncryptResetRepository;//用户密码状态的查询的DAO类
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
SecurityContext securityContext = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT"); // 获取session中的SecurityContext对象,它包含了用户的信息
User user = (User) securityContext.getAuthentication().getPrincipal();
if ( !user.equals(null) ) { // 说明已经登录了
UserEncryptReset uer = userEncryptResetRepository.findOneByUsername(user.getUsername()); //查询记录用户密码状态的对象
if ((uer != null) && (uer.getPasswordState().equals("1"))) { //uer存在并且用户密码状态为过期状态,才不允许放行
response.sendRedirect("/#/passwordReset"); // 将用户
return false;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
return;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}
----------
分享自//www.greatytc.com/p/dc5cc2e25ab2
注册拦截器
@Configuration // 配置
public class WebConfigfilter extends WebMvcConfigurerAdapter{
@Autowired
private PasswordStateInterceptor passwordStateInterceptor; // 实例化拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
// super.addInterceptors(registry);
// 注册自定义的拦截器passwordStateInterceptor
registry.addInterceptor(passwordStateInterceptor)
.addPathPatterns("/api/*") //匹配要过滤的路径
.excludePathPatterns("/api/changePasswordByUser/*") //匹配不过滤的路径。密码还要修改呢,所以这个路径不能拦截
.excludePathPatterns("/api/passwordStateValid") //密码状态验证也不能拦截
.excludePathPatterns("/api/getManagerVersion");//版本信息同样不能拦截
}
}
----------
分享自//www.greatytc.com/p/dc5cc2e25ab2
- 继承HandlerInterceptorAdapter并实现