• Spring Web MVC框架( 配置Spring Web MVC)


     

    这一篇文章对应于Spring参考文档 Configuring Spring MVC,讲的是Spring Web MVC各部分的配置方法,包括Java代码配置和XML文件配置以及MVC命名空间的使用方法。

    启用MVC Java配置和XML命名空间

    默认配置

    要启用MVC Java配置(@Controller等各种注解)和XML命名空间,如果使用的是Java配置,在配置类上再添加@EnableWebMvc注解即可。

    @Configuration
    @EnableWebMvc
    public class WebAppConfig {
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    如果使用XML配置文件的话,添加下面一行即可。

    <mvc:annotation-driven/>
    • 1

    不论使用哪种方式,都会在Spring中注册一些组件来提供最基本的MVC功能。这些功能在文档中说的很清楚。我简单翻译了一下:

    上面的配置会注册一个RequestMappingHandlerMapping,一个RequestMappingHandlerAdapter和一个ExceptionHandlerExceptionResolver来提供注解控制器和注解方法(比如@RequestMapping和@ExceptionHandler等)处理请求的功能。

    还会启用以下功能:

    • 通过一个ConversionService实例,来进行Spring 3 方式的类型转换及数据绑定支持。
    • @NumberFormat格式化数字字段的支持
    • @DateTimeFormat格式化DateCalendarLong、JodaTime类型字段的支持。
    • 在控制器方法上使用@Valid验证Bean的支持,如果检测到JSR-303 Bean验证的实现。
    • 一组HttpMessageConverter,用于在字符串和所需Java类型之间进行类型转换,具体的列表参见Spring文档 22.16.1. Enabling the MVC Java Config or the MVC XML Namespace

    通过这些默认配置,我们即可开始最基本的Spring MVC使用。

    自定义配置

    上面提供了最基本的配置。如果需要自定义某些配置也可以。如果使用Java配置的话,让配置类实现WebMvcConfigurer接口,更常用的办法是继承WebMvcConfigurerAdapter基类,通过重写基类中的方法即可配置相关功能。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
            //有很多个方法可以重写,来提供自定义功能
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果使用XML配置文件,通过IDE的自动补全功能查看一下<mvc:annotation-driven/>有哪些子属性和子元素。

    类型转换和格式化

    默认情况下Spring注册了Number(包括所有基本数字类型)和java.util.Date的类型转换和格式化功能。要提供类型的转换和格式化功能,就需要自己注册相应的类型转换器和格式化器。

    如果使用Java配置的话,重写addFormatters(FormatterRegistry registry)方法并添加相应功能即可。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addFormatters(FormatterRegistry registry) {
            // Add formatters and/or converters
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如果使用XML配置的话,需要注册一个ConversionService,然后添加到<mvc:annotation-driven>节点中。

        <mvc:annotation-driven conversion-service="conversionService"/>
    
        <bean id="conversionService"
                class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <bean class="org.example.MyConverter"/>
                </set>
            </property>
            <property name="formatters">
                <set>
                    <bean class="org.example.MyFormatter"/>
                    <bean class="org.example.MyAnnotationFormatterFactory"/>
                </set>
            </property>
            <property name="formatterRegistrars">
                <set>
                    <bean class="org.example.MyFormatterRegistrar"/>
                </set>
            </property>
        </bean>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    验证功能

    Spring自己提供了一组接口和类提供了一套验证功能。不过更通用的方法是使用Bean Validation进行Java对象的验证,Bean Validation的一个实现就是Hibernate Validator。如果想简单了解一下Hibernate Validator,可以看一下我的文章Hibernate Validator简介。如果需要详细使用方法请查看相关文档博客。

    默认情况下当@EnableWebMvc<mvc:annotation-driven/>配置之后,如果Spring检测到Bean Validation,就会自动注册一个LocalValidatorFactoryBean来提供验证功能。如果我们希望手动处理验证过程,可能希望将验证器实例注入到控制器中,这时候就不能使用自动注册的LocalValidatorFactoryBean了。这时候我们可以选择手动注册一个LocalValidatorFactoryBeanBean实例,然后注解@Primary让自定义LocalValidatorFactoryBean被优先使用。

    还有一种办法就是直接覆盖Spring的默认验证器配置。如果使用Java配置的话,重写getValidator()方法即可。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public Validator getValidator() {
            // return "global" validator
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如果使用XML配置文件,定义一个Validator然后添加到<mvc:annotation-driven>中。

    <mvc:annotation-driven validator="globalValidator"/>
    • 1

    上面定义的都是全局验证器,我们也可以在某个控制器中定义一个局部验证器,然后和全局验证器结合起来使用。这时候需要使用@InitBinder注解方法。

    @Controller
    public class MyController {
    
        @InitBinder
        protected void initBinder(WebDataBinder binder) {
            binder.addValidators(new FooValidator());
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    配置好验证器之后。当Spring识别到@Valid注解的方法参数之后,就会执行验证,将验证结果绑定到BindingResult上,我们可以在方法中访问BindingResult来获取验证结果。

    拦截器

    我们实现了拦截器之后,就可以将其应用到Web程序中。使用Java配置的话,重写addInterceptors(InterceptorRegistry registry)方法,然后在其中添加自己的拦截器即可。如果要配置拦截路径和排除路径也可以在这里配置。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LocaleInterceptor());
            registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
            registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用XML配置文件的话可以使用MVC命名空间,配置也比较简单。

    <mvc:interceptors>
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/admin/**"/>
            <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/secure/*"/>
            <bean class="org.example.SecurityInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    视图控制器

    这是一种定义ParameterizableViewController的简单方式,当该控制器被请求的时候不会执行任何逻辑操作,直接转到相应视图。视图控制器的常见用法是将网站的首页直接和/请求映射。

    使用Java配置可以这样写,下面的配置将/映射到名为index的视图。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("index");
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用XML配置也很简单。

    <mvc:view-controller path="/" view-name="index"/>
    • 1

    视图解析器

    使用Java配置,只需要重写configureViewResolvers(ViewResolverRegistry registry)方法即可。下面配置了JSP视图。如果需要其它视图解析器可以参见其相应文档,以及ViewResolverRegistry的JavaDoc。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            registry.enableContentNegotiation(new MappingJackson2JsonView());
            registry.jsp()
                    .prefix("/WEB-INF/jsp/")
                    .suffix(".jsp")
                    .viewClass(JstlView.class);
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如果使用XML配置文件可以使用MVC命名空间简化配置。除了内置的JSP解析器外,其它视图解析器可能还需要额外的配置,这里不再细述。

    <mvc:view-resolvers>
        <mvc:jsp prefix="/WEB-INF/jsp/"
                 suffix=".jsp"
                 view-class="org.springframework.web.servlet.view.JstlView"/>
    </mvc:view-resolvers>
    • 1
    • 2
    • 3
    • 4
    • 5

    资源处理

    静态资源处理

    这里说的主要是静态资源的处理。前面说了很多关于控制器、视图的知识,但是如何映射CSS、JS文件,前面没有说明。配置方法在这里说明。

    使用Java配置的话,重写addResourceHandlers(ResourceHandlerRegistry registry)方法,然后添加相应的映射即可。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**").addResourceLocations("/resources/static/");
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    使用XML配置文件 也同样简单。

    <mvc:resources mapping="/static/**" location="/resources/static/"/>
    • 1

    这样映射之后,假如我们有/resources/static/bootstrap.css文件,那么就可以使用/static/bootstrap.css路径来访问该文件了。同样的在视图文件中也可以如此引用。还可以使用cache-period设置资源的过期时间,单位是秒。如果需要指定多个资源位置,可以使用逗号分隔。

    资源的版本控制

    有些频繁更新的资源可能需要版本控制,强制让客户端使用最新的资源。Spring框架也支持资源的版本控制,我们需要定义资源链来实现这个功能。资源链由一个ResourceResolver实例和多个ResourceTransformer实例组成。内建的VersionResourceResolver能满足我们的大部分需求,它可以定义一些策略来配置版本控制,例如FixedVersionStrategy会依据日期、版本号或者其他东西作为版本;ContentVersionStrategy会计算资源的MD5值。

    ContentVersionStrategy策略是一个不错的策略,不过由于它会计算MD5,所以开销比较大, 因此在使用这种策略的时候最好打开缓存来提高性能。

    如果使用Java配置的话,和前面的例子差不多,只不过需要多调用resourceChain(true)等方法并添加相应的版本资源解析器和版本策略。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**")
                    .addResourceLocations("/resources/static/")
                    .resourceChain(true).addResolver(
                        new VersionResourceResolver().addContentVersionStrategy("/**"));
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    下面是使用XML配置的例子。

    <mvc:resources mapping="/static/**" location="/resources/static/">
        <mvc:resource-chain>
            <mvc:resource-cache/>
            <mvc:resolvers>
                <mvc:version-resolver>
                    <mvc:content-version-strategy patterns="/**"/>
                </mvc:version-resolver>
            </mvc:resolvers>
        </mvc:resource-chain>
    </mvc:resources>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    默认Servlet

    开启这个选项可以让DispatcherServlet处理根路径/下的静态资源请求,说的详细点就是假如静态文件是webapp/css/site.css,那么我们可以直接通过/css/site.css来访问这个文件。如果不启用这个功能,那么静态文件就只能映射到其他路径下比如/static

    这个配置项实际上会配置一个DefaultServletHttpRequestHandler,映射到路径/**,并具有最低的优先级。由于DefaultServletHttpRequestHandler会将所有请求转发到默认Servlet,所以它必须被配置为最后一个处理映射才行。

    使用Java配置的话,重写configureDefaultServletHandling(...)方法并开启该选项。

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如果使用XML配置的话,添加以下行。

    <mvc:default-servlet-handler/>
    • 1

    消息转换

    如果我们需要覆盖Spring默认的消息转换器,可以重写configureMessageConverters(List<HttpMessageConverter<?>> converters)方法,然后向converters参数添加我们自己的消息转换器。如果仅仅希望增加自己的类型转换器,重写extendMessageConverters()方法。

    使用XML配置文件的话,可以使用MVC命名空间。

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper" ref="objectMapper"/>
            </bean>
            <bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
                <property name="objectMapper" ref="xmlMapper"/>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    高级自定义配置

    上面的配置使用Spring提供的简化类或者MVC命名空间,帮助我们快速配置功能。有时候可能需要更高级的功能定制,这样就需要自己处理这些底层Bean的初始化和属性设置。

    Java配置自定义

    我们先来看一看@EnableWebMvc注解的定义。可以看到它还使用了一个@Import注解,引用了DelegatingWebMvcConfiguration类。当我们注解@EnableWebMvc的时候,实际上初始化和配置的底层类就是DelegatingWebMvcConfiguration

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(DelegatingWebMvcConfiguration.class)
    public @interface EnableWebMvc {
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    因此我们如果要自定义MVC的话,第一件事就是移除注解@EnableWebMvc。然后继承DelegatingWebMvcConfiguration类并实现它的requestMappingHandlerAdapter()方法。

    @Configuration
    public class WebConfig extends DelegatingWebMvcConfiguration {
    
        @Override
        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            // 在这里进行高级配置
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在项目中DelegatingWebMvcConfiguration子类和@EnableWebMvc注解配置类只能存在一个,因为它们做的事情实际上是一样的。而且这里的配置并不影响Spring MVC的其他配置。

    自定义MVC命名空间配置

    这里的自定义配置更困难,因为Spring没有提供相应的配置机制。如果实在需要自定义MVC命名空间配置,可以考虑使用Spring提供的BeanPostProcessor机制,在检测到Bean之后修改它的值。

    @Component
    public class MyPostProcessor implements BeanPostProcessor {
    
        public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
            if (bean instanceof RequestMappingHandlerAdapter) {
                // 在这里自定义属性
            }
        }
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
     
  • 相关阅读:
    如何优雅地关闭资源
    JMeter使用教程2——MySQL压测
    JMeter使用教程
    Redis系列(五):消息队列
    Redis系列(四):地理信息
    Redis系列(三):Bitmaps和HyperLogLog
    Redis系列(二):常用操作
    Redis系列(一):安装
    linux命令学习_实验楼(总结)
    【转】Linux中常用的tar解压打包命令语法介绍
  • 原文地址:https://www.cnblogs.com/jiadp/p/9334746.html
Copyright © 2020-2023  润新知