springMVC06-注解+配置类实现springMVC
目的:使用配置类+注解,代替:web.xml和springMVC的配置文件!
一、创建初始化类,替代web.xml
从 Servlet 3.0 开始,可以不写 web.xml
,改用 Java 类注册 DispatcherServlet,这种方式叫做:基于 Java 的初始化器配置(Java Config)。
最推荐写法:继承 Spring 提供的 AbstractAnnotationConfigDispatcherServletInitializer
/*** web工程的初始化类,用来代替web.xml*/
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {/*** 执行spring的配置类* @return*/@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}// 设置springMVC的配置类@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{WebMvcConfig.class};}/*** 指定dispatherServlet的映射规则,即:url-pattern* @return*/@Overrideprotected String[] getServletMappings() {return new String[]{"/"}; // 拦截所有请求}/*** 注册过滤器* @return*/@Overrideprotected Filter[] getServletFilters() {CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();// 请求设置编码characterEncodingFilter.setEncoding("UTF-8");// 响应设置编码characterEncodingFilter.setForceResponseEncoding(true);// 支持RESTful方式提交PUT/DELETEHiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};}
}
项目目录结构:
对比之前的web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- 注册 DispatcherServlet,对浏览器发送的请求统一处理 --><servlet><!--这个 <servlet-name> 其实是给 DispatcherServlet 起的一个“别名”自定义它与配置文件名有关!当你不给 DispatcherServlet 指定配置文件路径时(省略 <init-param>),Spring 会默认去加载这个路径:/WEB-INF/<servlet-name>-servlet.xml示例:如果你写成:<servlet-name>abc</servlet-name>默认加载:/WEB-INF/abc-servlet.xml但是可以通过 <init-param> 指定配置文件:--><servlet-name>springMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 加载 SpringMVC 配置文件:/resource/springMVC.xml --><init-param><param-name>contextConfigLocation</param-name><!--classpath:默认就是当前项目下的resources文件夹下--><param-value>classpath:springMVC.xml</param-value></init-param><!--指定当前 Servlet 是否在服务器启动时立即加载(初始化),以及加载的优先级。--><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springMVC</servlet-name><!--给 Servlet(如 DispatcherServlet)指定它要拦截哪些 URL 请求设置 springMVC 的核心控制器所能处理的请求的请求路径/ 所匹配的请求可以是 /login 或.html 或.js 或.css 方式的请求路径但是 / 不能匹配.jsp 请求路径的请求/*,匹配所有的请求路径,包括.jsp 请求路径的请求--><url-pattern>/</url-pattern></servlet-mapping><!-- 处理编码的过滤器 --><filter><filter-name>encodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 请求设置编码 --><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><!-- 响应设置编码 --><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 支持RESTful方式提交PUT/DELETE --><filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>
一个servlet,两个filter。
二、各部分配置类
2-1、WebMvcConfig.java
(SpringMVC 配置)
/*** springMVC的配置类:* 1、扫描组件 2、视图解析器 3、view-controller 4、default-servlet-handler(静态资源处理)* 5、注解驱动 6、文件上传解析器 7、异常处理 8、拦截器*/
@Configuration // 配置类的注解
@ComponentScan("com.wsbazinga.mvc.controller") // 扫描组件
@EnableWebMvc // 注解驱动
public class WebMvcConfig {// Thymeleaf 视图解析器// 1、Thymeleaf 模板解析器@Beanpublic SpringResourceTemplateResolver templateResolver(){/*WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());*/SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();// 视图前缀templateResolver.setPrefix("/WEB-INF/views/");// 视图后缀templateResolver.setSuffix(".html");templateResolver.setCharacterEncoding("UTF-8");templateResolver.setTemplateMode(TemplateMode.HTML);return templateResolver;}// 2、Thymeleaf 模板引擎@Beanpublic SpringTemplateEngine templateEngine() {SpringTemplateEngine engine = new SpringTemplateEngine();engine.setTemplateResolver(templateResolver());return engine;}// Thymeleaf 视图解析器@Beanpublic ThymeleafViewResolver viewResolver() {ThymeleafViewResolver resolver = new ThymeleafViewResolver();resolver.setTemplateEngine(templateEngine());resolver.setCharacterEncoding("UTF-8");resolver.setOrder(1); // 优先级return resolver;}}
对比之前的springMVC.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 开启注解驱动 --><mvc:annotation-driven/><!-- 扫描 Controller 包 --><context:component-scan base-package="com.wsbazinga.controller"/><!-- 视图解析器 --><bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><!-- 可以有多个视图解析器,用order属性配置优先级 --><property name="order" value="1"/><property name="characterEncoding" value="UTF-8"/><property name="templateEngine"><bean class="org.thymeleaf.spring5.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"><!-- 视图前缀 --><property name="prefix" value="/WEB-INF/views/"/><!-- 视图后缀 --><property name="suffix" value=".html"/><property name="characterEncoding" value="UTF-8"/><property name="templateMode" value="HTML5"/></bean></property></bean></property></bean></beans>
1、default-servlet-handler(静态资源处理)配置
它的作用是:
当 SpringMVC 拦截了请求后,如果没有匹配到任何
@RequestMapping
的 Controller,就把请求交给 Tomcat 默认的静态资源处理器(比如处理.css
,.js
,.png
等)。
原本springMVC.xml中的写法:
<!-- 静态文件处理 -->
<mvc:default-servlet-handler/>
你只需要在配置类中实现 WebMvcConfigurer
接口,并重写一个方法:
/*** springMVC的配置类:* 1、扫描组件 2、视图解析器 3、view-controller 4、default-servlet-handler(静态资源处理)* 5、注解驱动 6、文件上传解析器 7、异常处理 8、拦截器*/
@Configuration
@ComponentScan("com.wsbazinga.mvc.controller") // 扫描组件
@EnableWebMvc // 注解驱动
public class WebMvcConfig implements WebMvcConfigurer {/*** 相当于 <mvc:default-servlet-handler/>* 开启对静态资源的默认 servlet 处理*/@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable(); // 启用默认 servlet 处理}// Thymeleaf 视图解析器// ......}
【注意】:
快捷键: control + o,可以查看实现的接口里面,需要重写的方法,可以通过方法名确定。
2、配置拦截器
原本springMVC.xml中的写法:
<!-- 配置拦截器 --><mvc:interceptors><!--<bean class="com.wsbazinga.controller.MyInterceptor"></bean>--><!--<ref bean="myInterceptor"></ref>--><mvc:interceptor><mvc:mapping path="/**"/> <!-- 拦截所有请求 --><mvc:exclude-mapping path="/"/> <!-- 排除首页 --><bean class="com.wsbazinga.controller.MyInterceptor"></bean></mvc:interceptor><mvc:interceptor><mvc:mapping path="/**"/> <!-- 拦截所有请求 --><mvc:exclude-mapping path="/"/> <!-- 排除首页 --><bean class="com.wsbazinga.controller.SecondInterceptor"></bean></mvc:interceptor></mvc:interceptors>
编写两个拦截器类:
public class FirstInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("FirstInterceptor ---> preHandle");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("FirstInterceptor ---> postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("FirstInterceptor ---> afterCompletion");}
}
@Component
public class SecondInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("SecondInterceptor ---> preHandle");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("SecondInterceptor ---> postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("SecondInterceptor ---> afterCompletion");}
}
在WebMvcConfig配置类中重写addInterceptors方法:
/*** springMVC的配置类:* 1、扫描组件 2、视图解析器 3、view-controller 4、default-servlet-handler(静态资源处理)* 5、注解驱动 6、文件上传解析器 7、异常处理 8、拦截器*/
@Configuration
@ComponentScan("com.wsbazinga.mvc") // 扫描组件
@EnableWebMvc // 注解驱动
public class WebMvcConfig implements WebMvcConfigurer {@AutowiredSecondInterceptor secondInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 第一个拦截器registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**") // 拦截所有请求.excludePathPatterns("/"); // 排除首页// 第二个拦截器registry.addInterceptor(secondInterceptor).addPathPatterns("/**").excludePathPatterns("/");}// .......其余配置
}
如果希望从 Spring IOC容器中注入拦截器(加了
@Component
的方式),如:SecondInterceptor
必须加上@Component
注解。
3、配置view-controller
原本的springMVC.xml配置文件:
<!-- 配置首页的view-controller --><mvc:view-controller path="/" view-name="index"></mvc:view-controller><mvc:view-controller path="/test_rest" view-name="test_rest"></mvc:view-controller><mvc:view-controller path="/file" view-name="file"></mvc:view-controller>
配置类WebMvcConfig中重写如下方法:
// view-controller@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/hello").setViewName("hello");}
4、SpringMVC 的 XML 文件上传解析器配置
原本的springMVC.xml配置文件:
<!-- 处理文件上传的 Bean --><bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="maxUploadSize" value="5242880"/> <!-- 5MB --></bean>
这是为了启用对文件上传请求(multipart/form-data)的处理,常用于表单上传文件。
在配置类(如 WebMvcConfig
)中添加一个 @Bean
方法:
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {CommonsMultipartResolver resolver = new CommonsMultipartResolver();resolver.setMaxUploadSize(5242880); // 设置最大上传大小为 5MB// 可选配置:编码、缓冲大小等resolver.setDefaultEncoding("UTF-8");return resolver;
}
5、SimpleMappingExceptionResolver
配置异常跳转页面
原本的springMVC.xml配置文件:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><prop key="java.lang.ArithmeticException">error</prop></props></property><property name="exceptionAttribute" value="ex"/>
</bean>
这是一个<bean>,所以,在配置类中声明一个对应的
@Bean
方法。也可以:override
configureHandlerExceptionResolvers()
方法
@Overridepublic void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();Properties properties = new Properties();properties.setProperty("java.lang.ArithmeticException", "error");simpleMappingExceptionResolver.setExceptionMappings(properties);// 想要在error.html页面打印异常信息// 将异常set到请求域中simpleMappingExceptionResolver.setExceptionAttribute("exception");resolvers.add(simpleMappingExceptionResolver);}
三、完整的 WebMvcConfig配置类
完整的 WebMvcConfig配置类代码如下:
/*** springMVC的配置类:* 1、扫描组件 2、视图解析器 3、view-controller 4、default-servlet-handler(静态资源处理)* 5、注解驱动 6、文件上传解析器 7、异常处理 8、拦截器*/
@Configuration
@ComponentScan("com.wsbazinga.mvc") // 扫描组件
@EnableWebMvc // 注解驱动
public class WebMvcConfig implements WebMvcConfigurer {@AutowiredSecondInterceptor secondInterceptor;/*** 异常处理* @param resolvers*/@Overridepublic void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();Properties properties = new Properties();properties.setProperty("java.lang.ArithmeticException", "error");simpleMappingExceptionResolver.setExceptionMappings(properties);// 想要在error.html页面打印异常信息// 将异常set到请求域中simpleMappingExceptionResolver.setExceptionAttribute("exception");resolvers.add(simpleMappingExceptionResolver);}/*** 文件上传解析器* @return*/@Bean(name = "multipartResolver")public CommonsMultipartResolver multipartResolver() {CommonsMultipartResolver resolver = new CommonsMultipartResolver();resolver.setMaxUploadSize(5242880); // 设置最大上传大小为 5MB// 可选配置:编码、缓冲大小等resolver.setDefaultEncoding("UTF-8");return resolver;}// view-controller@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/hello").setViewName("hello");}/*** 拦截器* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 第一个拦截器registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**") // 拦截所有请求.excludePathPatterns("/"); // 排除首页// 第二个拦截器registry.addInterceptor(secondInterceptor).addPathPatterns("/**").excludePathPatterns("/");}/*** 相当于 <mvc:default-servlet-handler/>* 开启对静态资源的默认 servlet 处理*/@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable(); // 启用默认 servlet 处理}// Thymeleaf 视图解析器// 1、Thymeleaf 模板解析器@Beanpublic SpringResourceTemplateResolver templateResolver(){/*WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(webApplicationContext.getServletContext());*/SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();// 视图前缀templateResolver.setPrefix("/WEB-INF/views/");// 视图后缀templateResolver.setSuffix(".html");templateResolver.setCharacterEncoding("UTF-8");templateResolver.setTemplateMode(TemplateMode.HTML);return templateResolver;}// 2、Thymeleaf 模板引擎@Beanpublic SpringTemplateEngine templateEngine() {SpringTemplateEngine engine = new SpringTemplateEngine();engine.setTemplateResolver(templateResolver());return engine;}// Thymeleaf 视图解析器@Beanpublic ThymeleafViewResolver viewResolver() {ThymeleafViewResolver resolver = new ThymeleafViewResolver();resolver.setTemplateEngine(templateEngine());resolver.setCharacterEncoding("UTF-8");resolver.setOrder(1); // 优先级return resolver;}}