第八章:SpringMVC下
创建一个新的模块,spring_mvc_extension_17
,复用spring_mvc_ajax_16
的依赖、web.xml
、springmvc.xml
配置文件、index.html
和success.html
文件只用保留一个h1
标签即可。
8.1:拦截器
-
拦截器的配置
SpringMVC
中拦截器用于拦截控制器方法的执行,SpringMVC
中的拦截器需要实现Headlerinterceptor
,SpringMVC
的拦截器必须在SpringMVC
的配置文件中进行配置:<!-- 这两种方式是对DispatcherServlet所处理的所有的请求进行拦截 --> <!-- 方式一 --> <mvc:interceptors> <bean class="com.wang.interceptor.FirstInterceptor" /> </mvc:interceptors> <!-- 方式二 --> <mvc:interceptors> <ref bean="firstInterceptor" /> </mvc:interceptors>
<mvc:interceptors> <mvc:interceptor> <!-- path="/**" 是表示对所有请求进行拦截,一个星表示对一层的路径的请求拦截 --> <mvc:mapping path="/**"/> <!-- 排除拦截的请求 --> <mvc:exclude-mapping path="/abc"/> <ref bean="firstInterceptor" /> </mvc:interceptor> </mvc:interceptors>
-
拦截器的三个抽象方法
SpringMVC
中的拦截器有三个抽象方法:preHandle
:控制器方式之前执行preHandle()
,其boolean
类型的返回值表示是否拦截或放行,返回true
为放行,即调用控制器方法,返回false
表示拦截,即不调用控制器方法。postHandle
:控制器方法执行后执行postHandle()
。afterCompletion
:处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()
。
-
多个拦截器的执行顺序
-
若每个拦截器
preHandle()
都返回true
此时多个拦截器的执行顺序和拦截器在
SpringMVC
的配置文件的配置顺序有关。preHandle()
会按照配置的顺序执行,而postHandle()
和afterCompletion()
会按照配置的反序执行。 -
若某个拦截器
preHandle()
返回false
preHandle()
返回false
和他之前的拦截器的preHandle()
都会被执行,postHandle()
都不执行,返回false
的拦截器之前的拦截器的afterCompletion()
会执行。
-
8.2:异常处理器
-
基于配置的异常处理
SpingMVC
提供了一个处理控制器方法执行过程中所有出现的异常接口:DefaultHandlerExceptionResolver
和SimpleMappingExceptionResolver
。<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!-- key表示处理器方法执行过程中出现的异常 标签的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面 --> <prop key="java.lang.ArithmeticException">error</prop> </props> </property> <!-- exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享 --> <property name="exceptionAttribute" value="ex"></property> </bean>
@RequestMapping("/test/hello") public String testHello() { System.out.println(1/0); return "success"; }
-
基于注解的异常处理
// 将当前类标识为异常处理的组件 @ControllerAdvice public class ExceptionController { // 用于设置所标识方法处理的异常 @ExceptionHandler(ArithmeticException.class) public String handleException(Throwable ex, Model model) { model.addAttribute("ex", ex); return "error"; } }
8.3:注解配置SpringMVC
创建一个新的模块,spring_mvc_annotation_18
,复用spring_mvc_extension_17
的依赖。
-
初始化类,代替
web.xml
在
Servlet 3.0
环境中,容器会在类路径中查找实现javax.servlet.ServletContaionerInitalizer
接口的类,如果找到的话就用它来配置Servlet
容器。Spring
提供了这个接口的实现,名为SpringServletContaionerInitalizer
,这个类反过来又会查找实现WebApplicationInitializer
基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer
,当我们的类扩展了这个类,并将其部署到Servlet 3.0
容器的时候,容器会自动发现他,并用它来配置Servlet
上下文。package com.wang.config; public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer { // 设置一个配置类代替Spring的配置文件 @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } // 设置一个配置类代替SpringMVC的配置文件 @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } //设置SpringMVC的前端控制器DispatcherServlet的url-pattern @Override protected String[] getServletMappings() { return new String[]{"/"}; } // 设置当前的过滤器 @Override protected Filter[] getServletFilters() { // 创建编码过滤器 CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setForceEncoding(true); // 创建处理请求方式的过滤器 HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter}; } }
-
创建
Web Config
配置类,代替SpringMVC
的配置文件package com.wang.config; // 0.将类标识为配置类 @Configuration // 1.扫描组件 @ComponentScan("com.wang.controller") // 4.MVC注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { // 2. 视图解析器 // 2.1生成视图解析器并为解析器注入模板引擎 @Bean public ViewResolver viewResolver(SpringTemplateEngine templateEngine) { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setCharacterEncoding("UTF-8"); viewResolver.setTemplateEngine(templateEngine); return viewResolver; } // 2.2生成模板引擎并为模板注入模板解析器 @Bean public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); return templateEngine; } // 2.3配置生成视图解析器 @Bean public ITemplateResolver templateResolver() { WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext(); ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver( webApplicationContext.getServletContext() ); templateResolver.setPrefix("/WEB-INF/templates/"); templateResolver.setSuffix(".html"); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); return templateResolver; } // 3.默认的servlet处理静态资源 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } // 5.视图控制器 @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); } // 6.文件上传解析器 @Bean public CommonsMultipartResolver multipartResolver() { return new CommonsMultipartResolver(); } // 7.拦截器,自行创建FirstInterceptor类用于拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { FirstInterceptor firstInterceptor = new FirstInterceptor(); registry.addInterceptor(firstInterceptor).addPathPatterns("/**"); } // 8.配置异常解析器 @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); Properties prop = new Properties(); prop.setProperty("java.lang.ArithmeticException", "error"); exceptionResolver.setExceptionMappings(prop); exceptionResolver.setExceptionAttribute("ex"); resolvers.add(exceptionResolver); } }