springMVC06-注解+配置类实现springMVC

发布于:2025-07-10 ⋅ 阅读:(14) ⋅ 点赞:(0)

目的:使用配置类+注解,代替: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
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    // 设置springMVC的配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebMvcConfig.class};
    }

    /**
     * 指定dispatherServlet的映射规则,即:url-pattern
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"}; // 拦截所有请求
    }

    /**
     * 注册过滤器
     * @return
     */
    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        // 请求设置编码
        characterEncodingFilter.setEncoding("UTF-8");
        // 响应设置编码
        characterEncodingFilter.setForceResponseEncoding(true);

        // 支持RESTful方式提交PUT/DELETE
        HiddenHttpMethodFilter 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 模板解析器
    @Bean
    public 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 模板引擎
    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver());
        return engine;
    }

    // Thymeleaf 视图解析器
    @Bean
    public 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/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://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 处理
     */
    @Override
    public 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 {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("FirstInterceptor ---> preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("FirstInterceptor ---> postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("FirstInterceptor ---> afterCompletion");
    }
}
@Component
public class SecondInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("SecondInterceptor ---> preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("SecondInterceptor ---> postHandle");
    }

    @Override
    public 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 {

    @Autowired
    SecondInterceptor secondInterceptor;

    @Override
    public 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
    @Override
    public 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() 方法

    @Override
    public 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 {

    @Autowired
    SecondInterceptor secondInterceptor;

    /**
     * 异常处理
     * @param resolvers
     */
    @Override
    public 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
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/hello").setViewName("hello");
    }

    /**
     * 拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 第一个拦截器
        registry.addInterceptor(new FirstInterceptor())
                .addPathPatterns("/**")      // 拦截所有请求
                .excludePathPatterns("/");   // 排除首页

        // 第二个拦截器
        registry.addInterceptor(secondInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/");
    }

    /**
     * 相当于 <mvc:default-servlet-handler/>
     * 开启对静态资源的默认 servlet 处理
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable(); // 启用默认 servlet 处理
    }

    // Thymeleaf 视图解析器
    // 1、Thymeleaf 模板解析器
    @Bean
    public 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 模板引擎
    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver());
        return engine;
    }

    // Thymeleaf 视图解析器
    @Bean
    public ThymeleafViewResolver viewResolver() {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine());
        resolver.setCharacterEncoding("UTF-8");
        resolver.setOrder(1); // 优先级
        return resolver;
    }

}

网站公告

今日签到

点亮在社区的每一天
去签到