youyichannel

志于道,据于德,依于仁,游于艺!

0%

SpringMVC相关知识

SpringMVC的核心组件

记住了核心组件,工作原理也就顺理成章可以推导出来了。

  1. DispatcherServlet:核心中央处理器,负责接收请求、分发,并给予客户端相应
  2. HandlerMapping:处理器映射器,根据URL去匹配查找能处理的Handler,并会将请求涉及到的拦截器和Handler一起封装
  3. HandlerAdapter:处理器适配器,根据HandlerMapping找到的Handler,适配执行对应的Handler
  4. Handler:请求处理器,处理实际请求的处理器
  5. ViewResolver:视图解析器,根据Handler返回的逻辑视图 / 视图,解析并渲染真正的视图,并传递给DispatcherServlet相应客户端

SpringMVC的工作原理

流程说明:

  1. 客户端(浏览器)发送请求,DispatcherServlet拦截请求
  2. DispatcherServlet根据请求信息调用HandlerMappingHandlerMapping根据URL去匹配查找能处理的Handler(即Controller),并会将请求涉及到的拦截器和Handler一起封装
  3. DispatcherServlet调用HandlerAdapater适配器执行Handler
  4. Handler完成用户请求的处理后,返回一个ModelAndView对象给DispatcherServlet
  5. ViewResolver会根据逻辑View查找实际的View
  6. DispatcherServlet把返回的Model传给View(视图渲染)
  7. View渲染结果返回给客户端(浏览器)

参考:https://www.jianshu.com/p/8a20c547e245

如何处理统一异常处理

推荐使用注解的方式统一异常处理,具体会使用到 @ControllerAdvice + @ExceptionHandler 这两个注解 。

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

@ExceptionHandler(BaseException.class)
public ResponseEntity<?> handleAppException(BaseException ex, HttpServletRequest request) {
//......
}

@ExceptionHandler(value = ResourceNotFoundException.class)
public ResponseEntity<ErrorReponse> handleResourceNotFoundException(ResourceNotFoundException ex, HttpServletRequest request) {
//......
}
}

这种异常处理方式下,会给所有或者指定的 Controller 织入异常处理的逻辑(AOP),当 Controller 中的方法抛出异常的时候,由被@ExceptionHandler 注解修饰的方法进行处理。

ExceptionHandlerMethodResolvergetMappedMethod 方法决定了异常具体被哪个被 @ExceptionHandler 注解修饰的方法处理异常。

/**
* Return the {@link Method} mapped to the given exception type, or
* {@link #NO_MATCHING_EXCEPTION_HANDLER_METHOD} if none.
*/
private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
List<Class<? extends Throwable>> matches = new ArrayList<>();
// 找到可以处理的所有异常信息,mappedMethods中存放了异常和处理异常的方法的对应关系
for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
if (mappedException.isAssignableFrom(exceptionType)) {
matches.add(mappedException);
}
}
// 不为空说明有方法处理异常
if (!matches.isEmpty()) {
// 升序排序,取最小的那一个匹配的方法(即匹配度最高的方法)
if (matches.size() > 1) {
matches.sort(new ExceptionDepthComparator(exceptionType));
}
// 返回处理异常的方法
return this.mappedMethods.get(matches.get(0));
}
else {
return NO_MATCHING_EXCEPTION_HANDLER_METHOD;
}
}