花钱做网站需要所有权,建设厅网站打不开,网站开发电脑配置,不备案怎么做淘宝客网站吗1、异常处理 在DispatcherServlet中#xff0c;doDispatch(HttpServletRequest request, HttpServletResponse response) 方法用于进行任务处理#xff1a; 在捕获到异常后没有立刻进行处理#xff0c;而是先用一个局部变量dispatchException进行记录#xff0c;然后统一由…1、异常处理 在DispatcherServlet中doDispatch(HttpServletRequest request, HttpServletResponse response) 方法用于进行任务处理 在捕获到异常后没有立刻进行处理而是先用一个局部变量dispatchException进行记录然后统一由processDispatchResult() 方法进行处理 processDispatchResult() 方法中首先判断异常是否为空如果为空就不进行处理然后判断是否是ModelAndViewDefiningException类型异常如果不是就进入processHandlerException() processHandlerException() 中会循环遍历handlerExceptionResolvers集合去匹配并处理异常 Nullableprivate ListHandlerExceptionResolver handlerExceptionResolvers; HandlerExceptionResolver是一个接口我们使用ExceptionHandlerExceptionResolver的实现去模拟异常处理的过程 ExceptionHandlerExceptionResolver专门用于解析 ExceptionHandler注解把标注了 ExceptionHandler注解的方法作为处理异常的方法
//专门用于解析 ExceptionHandler注解把标注了 ExceptionHandler注解的方法作为处理异常的方法
ExceptionHandlerExceptionResolver resolver new ExceptionHandlerExceptionResolver();
//设置消息转换json
resolver.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
//初始化 加入常用的参数和返回值解析器
resolver.afterPropertiesSet();testJSON(resolver); 在afterPropertiesSet() 初始化方法中已经预先定义好了一些参数解析器和返回值处理器 定义一个控制器
public class Controller1 {public void foo(){}/*** 处理异常的方法并且将返回值转成JSON* param e* return*/ExceptionHandlerResponseBodypublic MapString,Object handle(ArithmeticException e){return Collections.singletonMap(error,e.getMessage());}
} resolver.resolveException()方法会检查Controller1中是否有ExceptionHandler注解标注的方法如果有并且参数的异常和实际发生的异常能对应上就执行其中的逻辑 private static void testJSON(ExceptionHandlerExceptionResolver resolver) throws NoSuchMethodException {MockHttpServletRequest request new MockHttpServletRequest();MockHttpServletResponse response new MockHttpServletResponse();//将控制器的foo方法封装成HandlerMethod对象HandlerMethod handlerMethod new HandlerMethod(new Controller1(),Controller1.class.getMethod(foo));//检查Controller1中是否有ExceptionHandler注解标注的方法如果有并且参数的异常和实际发生的异常能对应上就执行其中的逻辑resolver.resolveException(request,response,handlerMethod,new ArithmeticException(数学异常));System.out.println(new String(response.getContentAsByteArray(), StandardCharsets.UTF_8));} 此外处理异常的方法还支持ModelAndView类型的返回与上述解析异常的过程相似。 我们还可以转发自定义的错误处理页面 /*** 转发到自定义的错误页面* return*/Beanpublic ErrorPageRegistrar errorPageRegistrar(){return new ErrorPageRegistrar() {Overridepublic void registerErrorPages(ErrorPageRegistry registry) {registry.addErrorPages(new ErrorPage(/error));}};}/*** 注册后处理器* return*/Beanpublic ErrorPageRegistrarBeanPostProcessor errorPageRegistrarBeanPostProcessor(){return new ErrorPageRegistrarBeanPostProcessor();}/*** Spring Boot中配置自定义的BasicErrorController用于处理基本的错误页面和错误信息。* return*/Beanpublic BasicErrorController basicErrorController(){ErrorProperties errorProperties new ErrorProperties();errorProperties.setIncludeException(true);return new BasicErrorController(new DefaultErrorAttributes(),errorProperties);}
2、BeanNameUrlHandlerMappingSimpleControllerHandlerAdapter BeanNameUrlHandlerMapping和SimpleControllerHandlerAdapter分别是HandlerMapping和HandlerAdapter的实现类 在BeanNameUrlHandlerMapping中以/开头的 bean 的名字会被当作映射路径。这些 bean 本身当作 handler要求实现 Controller 接口。 准备一个Config类将BeanNameUrlHandlerMapping和SimpleControllerHandlerAdapter注册成bean
Configuration
ComponentScan
PropertySource(classpath:application.properties)
EnableConfigurationProperties({WebMvcProperties.class, ServerProperties.class})//将配置文件中的属性绑定到对象中
public class Config {/*** 注册内嵌web容器工厂 tomcat容器*/Beanpublic TomcatServletWebServerFactory tomcatServletWebServerFactory(){return new TomcatServletWebServerFactory();}/*** 创建DispatcherServlet* 首次使用时由tomcat容器初始化* return*/Beanpublic DispatcherServlet dispatcherServlet(){return new DispatcherServlet();}/*** 注册DispatcherServlet springmvc入口* param dispatcherServlet* return*/Beanpublic DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet,WebMvcProperties webMvcProperties){DispatcherServletRegistrationBean registrationBean new DispatcherServletRegistrationBean(dispatcherServlet, /);//设置tomcat容器启动时即进行DispatcherServlet初始化registrationBean.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());return registrationBean;}Beanpublic BeanNameUrlHandlerMapping beanNameUrlHandlerMapping(){return new BeanNameUrlHandlerMapping();}Beanpublic SimpleControllerHandlerAdapter simpleControllerHandlerAdapter(){return new SimpleControllerHandlerAdapter();}Bean(/c3)public Controller controller3(){return (request, response) - {response.getWriter().print(this is c3);return null;};}}再准备两个实现了Controller接口的控制器类
Component(/c1)
public class Controller1 implements Controller {Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {response.getWriter().print(this is c1);return null;}
}Component(c2)
public class Controller2 implements Controller {Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {response.getWriter().print(this is c2);return null;}
} 启动主类
public class A31 {public static void main(String[] args) {AnnotationConfigServletWebServerApplicationContext context new AnnotationConfigServletWebServerApplicationContext(Config.class);}
}我们可以模拟实现这一组映射器和适配器 定义一个类实现BeanNameUrlHandlerMapping的顶级接口HandlerMapping 它的作用是在初始化时收集容器中所有以/开头的路径和类成map集合并且在调用时会判断当前requestURI能否与map集合中的任意元素相匹配 复习一下容器初始化时会收集所有 RequestMapping 映射信息封装为 Map
/*** 模拟处理器映射器* 收集请求中以/开头的bean*/
Component
public class MyHandlerMapping implements HandlerMapping {/*** 处理器映射器getHandlerMethods中 和当前requestURI 匹配的路径信息* param request* return* throws Exception*/Overridepublic HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {String requestURI request.getRequestURI();Controller controller map.get(requestURI);//匹配不上 404if (controller null){return null;}return new HandlerExecutionChain(controller);}Autowiredprivate ApplicationContext applicationContext;private MapString, Controller map;/*** 初始化时收集所有容器中/开头的bean信息*/PostConstructpublic void init() {MapString, Controller beansOfType applicationContext.getBeansOfType(Controller.class);map beansOfType.entrySet().stream().filter(e - e.getKey().startsWith(/)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));System.out.println(map);}
} 定义一个类实现HandlerAdapter作为适配器负责将请求分派给实现了controller接口类中的方法和RequestMappingHandlerAdapter相比不需要自定义参数和返回值处理器。
/*** 模拟处理器适配器*/
Component
public class MyHandlerAdapter implements HandlerAdapter {/*** 判断传递的handler是否是当前MyHandlerAdapt支持的* param handler* return*/Overridepublic boolean supports(Object handler) {return handler instanceof Controller;}/*** 调用实现了Controller接口的方法* 无需参数解析器返回值处理器* param request* param response* param handler* return* throws Exception*/Overridepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (handler instanceof Controller){((Controller) handler).handleRequest(request, response);}return null;}Overridepublic long getLastModified(HttpServletRequest request, Object handler) {return -1;}
} 结论Controller1和Controller3能匹配上Controller2匹配不上路径中没有/
3、RouterFunctionMappingHandlerFunctionAdapter RouterFunctionMapping和HandlerFunctionAdapter也是HandlerMapping和HandlerAdapter的实现类
RouterFunctionMapping会收集所有的RouterFunction请求到达时根据条件找到HandlerFunctionHandlerFunctionAdapter会调用符合条件的HandlerFunction。
/*** 会收集所有的RouterFunction* 请求到达时根据条件找到HandlerFunction* return*/Beanpublic RouterFunctionMapping routerFunctionMapping(){return new RouterFunctionMapping();}/*** 调用符合条件的HandlerFunction* return*/Beanpublic HandlerFunctionAdapter handlerFunctionAdapter(){return new HandlerFunctionAdapter();} RouterFunction分为两部分匹配规则和具体的执行逻辑请求是GET类型并且路径是/r1就执行new HandlerFunctionServerResponse()中的逻辑 Beanpublic RouterFunctionServerResponse r1(){//参数一 匹配规则 参数二 具体的执行逻辑return RouterFunctions.route(RequestPredicates.GET(/r1), new HandlerFunctionServerResponse() {Overridepublic ServerResponse handle(ServerRequest request) throws Exception {return ServerResponse.ok().body(this is r1);}});} 下一篇对Spring MVC 的执行流程做一个总结。