[spring]applicationContext.xml-mvc标签

紧接着上文,我们来学习mvc标签。

Spring版本:4.3.14。

6.mvc 命名空间

  mvc命名空间内的标签是用于Spring MVC的配置,一般情况下Spring的配置文件和Spring-MVC的配置文件都是分开配置的,Spring MVC的配置文件默认情况下是 dispatcher-servlet.xml,所以mvc的配置通常都是在该配置文件中。下面我们来学习下每个标签的用处。

  首先,记得先引入命名空间,并且先搭建好Spring MVC环境,这些都很简单,这里就不多说了。

6.1 标签

mvc:annotation-driven标签是一种简写的形式,用于为Spring MVC分发请求到Controller上,不过该标签支持的功能很多,比如@InitBinder数据绑定,@NumberFormatannotation数据格式化,@DateTimeFormat日期格式化,数据校验,@RequestBody @ResponseBody的json支持等;下面来看一下该标签中各个属性的配置。

6.1.1 ignore-default-model-on-redirect元素

顾名思义,用于请求重定向时是否忽略model的参数,布尔值,true和false,默认是false,但文档中建议应该设置为true:

The default setting is false but new applications should consider setting it to true.

有的时候,我们重定向的时候需要传参数,我们通过Model添加参数,通过ModelAttribute来获取URL的参数,但有些时候在重定向的时候,我们不想把参数带过去,比如说我们重定向的地址是:http://localhost:8080/hello/test.html?users=user1&users=user2&users=user3&users=user4...,这时候我们可以通过配置该属性为true,来忽略URL后面这一堆参数。
具体使用可参考:https://stackoverflow.com/questions/13247239/spring-mvc-controller-redirect-without-parameters-being-added-to-my-url%3C/b%3E

6.1.2 enable-matrix-variables元素

一般情况下,我们URL中很少会出现name-value这种类似于键值对的形式,而Spring MVC却提供了对这种形式的支持,在Spring MVC中,它们被称为matrix-variables。而如果要在Spring中使用该功能,需要先配置enable-matrix-variables属性,该属性是布尔类型,有true和false,默认情况下是false,也就是不开启的状态。

matrix variables的形式如:/cars;color=red,green;year=2012,其中各个变量之间使用分号分隔,每个变量如果多个值,使用逗号分割;简单看下官网的几个例子:

// GET /pets/42;q=11;r=22
@GetMapping("/pets/{petId}")
public void findPet(@PathVariable String petId, @MatrixVariable int q) {

    // petId == 42
    // q == 11
}

这里简单说下,GetMapping是Spring4.3之后的一个组合注解。我们在URL中配置相应的name-value组合之后,可以通过注解@MatrixVariable来获取该组合的值。如果要查看更多有关matrix-variables相关,可参考官网文件:https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-matrix-variables

6.1.3 conversion-service元素

在我们通过浏览器向我们的服务器提交数据的时候,也就是在字段绑定期间,用于类型转换的ConversionService的bean的名称,默认情况下的实现是FormattingConversionService,如果我们需要自定义转换类型的时候可以通过配置该bean指向我们自定义的转换器来实现。

自定义转换器:

public class DateConverter implements Converter {
    @Override
    public Date convert(String dateString) {
        try {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

引入我们的转换器,当然我们开可以配置多个转换器:


    
        
            
        
    

其实Spring已经给我们提供了许多种类型转换器,位于org.springframework.core.convert.support目录下,在以上转换器都不满足的情况下,我们可以自定义我们的类型转换器;并且使用的时候可以结合@InitBinder注解来一并学习使用。

6.1.4 message-codes-resolver元素

一般情况下,在浏览器传递参数到服务器的时候,我们都需要进行数据绑定,并且进行参数验证,如果绑定失败或者验证失败,对应的错误码会保存到Spring的错误对象中,而我们可以通过MessageCodesResolver来对错误code构建相应的message信息。默认情况下,Spring将使用DefaultMessageCodesResolver对象进行解析,当然如果有需要,我们也可以自定义我们的解析器。

6.1.5 validator元素

  上面我们也已经说过,对于从浏览器端传递过来的参数,前端的JS可以涵盖大部分的校验职责,但为了避免用户绕过浏览器,使用HTTP工具向后台直接发送一些非正常的数据,我们后台的校验也是必须的。
  而在这一点上,Java中的JSR303/JSR-349定义了相应的规范,而Bean Validation则是该规范的具体实现。Bean Validation是一个通过配置注解来验证参数的框架,它包含两部分Bean Validation API和Hibernate Validator:

  • Bean Validation API是Java定义的一个验证参数的规范。
  • Hibernate Validator是Bean Validation API的一个实现。

而我们如果在Spring中使用该框架的话,只需要简单配置即可:

  
      
      
      
  
  
      
          
              
            classpath:messages  
            classpath:org/hibernate/validator/ValidationMessages  
          
      
      
      
      
  

其中消息文件 ValidationMessages.properties 定义了我们配置的一些信息:

user.id.null=用户编号不能为空  
user.name.null=用户名不能为空  
user.name.length.illegal=用户名长度必须在5到20之间  
user.name.illegal=用户名必须是字母  
user.password.null=密码不能为空  

以上参考自:http://jinnianshilongnian.iteye.com/blog/1990081

6.1.6 content-negotiation-manager元素

  该元素中文一般翻译为内容协商,意思是同一资源可以多种展示方式,比如说当输入后缀是html的时候,返回html页面,当输入json后缀的时候,返回j'son格式的数据,当然是在同一个方法里,其实就是根据请求规则决定返回什么样的内容类型。
  比如说类似于这种:@RequestMapping(value={"/user/{id}","/user/{id}.json"}),也就是说当输入user/1的时候返回对应的试图,当输入user/1.json的时候,返回json格式的数据,这种就是所谓的内容协商了,而Spring中content-negotiation-manager该元素就是用于实现这个功能的,当然不单单是json,还有其他方式,比如XML等等。
在RESTful该特性的实现方式大概有以下三种:

  • 1.使用http request header: Accept
GET /user/123 HTTP/1.1
Accept: application/xml                 //将返回xml格式数据

GET /user/123 HTTP/1.1
Accept: application/json               //将返回json格式数据
    1. 使用扩展名
/user/123.xml  将返回xml格式数据
/user/123.json 将返回json格式数据
/user/123.html 将返回html格式数据
    1. 使用参数
/user/123?format=xml          //将返回xml数据
/user/123?format=json          //将返回json数据

而Spring则是支持以上三种方式的,ContentNegotiatingViewResolver是根据客户提交的MimeType(如 text/html,application/xml)来跟服务端的一组viewResover的MimeType相比较,如果符合,即返回viewResover的数据。
而 /user/123.xml, ContentNegotiatingViewResolver会首先将 .xml 根据mediaTypes属性将其转换成 application/xml,然后完成前面所说的比较。


    
    
    
    
    
        
            json=application/json
            xml=application/xml
        
    



    
    
        
            
        
    

如果想更多的了解内容协商相关的问题,可参考:
Spring MVC Content Negotiation
https://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc/
官网文档-mvc-config-content-negotiation

6.1.7 mvc:argument-resolvers子标签

该标签用于自定义参数解析器,比如说我们通过@RequestBody来解析json格式的参数,通过@RequestParam来解析表单相关的参数,如果Spring自带的参数解析器满足不了我们的需要,我们可以自定义解析器,实现HandlerMethodArgumentResolver接口,然后配合注解来完成自定义解析参数的功能。


    
        
    

6.1.8 mvc:return-value-handlers子标签

该标签表示允许我们对特定的返回类型做处理,看一个例子就明白了:、

@RequestMapping("/testReturnHandlers")
public User testHandlerReturnMethod(){
    User u  = new User();
    u.setUserName("test");
    return u;
}

  由于上面testReturnHandlers接口返回的是一个pojo类型,正常情况下Spring MVC无法解析,最后会由DefaultRequestToViewNameTranslator解析处一个缺省的view name,转到 testReturnHandlers.jsp,如果没有的话就会报错。这时候我们就可以通过该标签引入我们自定义的 HandlerMethodReturnValueHandler的实现来完成数据的处理。

这时候我们先自定义我们的返回Handler处理器:

public class UserHandlers implements HandlerMethodReturnValueHandler {
    Logger logger = LoggerFactory.getLogger(this.getClass());
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        Class type = returnType.getParameterType();
        if(User.class.equals(type))
        {
            return true;
        }
        return false;
    }

    @Override
    public void handleReturnValue(Object returnValue,
            MethodParameter returnType, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest) throws Exception {
        logger.info("handler  for return type users ");
        mavContainer.setViewName("helloworld");
    }
}

然后进行相关配置:


    
        
    

最终我们再访问testReturnHandlers的时候,Spring就会通过我们自定义的UserHandlers来处理返回类型是User的返回值;

6.1.9 mvc:path-matching子标签

该标签用于控制Spring MVC请求URL的路径匹配,比如说,我们的某个方法配置如下:

@RequestMapping("/world")
public String hello() {
    return "hello";
}

默认情况下,Spring MVC会自动匹配所有.*的请求,就上面这个例子而言,我们请求/world/wold.html/world.do都会匹配成功,然后执行相应的操作。如果我们不想按照Spring的这种默认的匹配规则来的话,就可以通过配置该标签来完成我们所需的操作。下面来简单看下该标签下的几个参数:

  1. suffix-pattern元素:布尔类型,true和false,该元素表示URL匹配的时候是否使用默认的后缀模式匹配全部(.*),默认是true,如果我们配置为false的话,那么就上面例子来说,我们再使用/world.*类似的就匹配不到了。
  2. trailing-slash元素:布尔类型,true和false,该属性表示匹配的时候是否不考虑斜杠/,默认是true,也就是不考虑斜杠的存在,那么映射到/users的方法也就可以匹配/users/
  3. registered-suffixes-only元素:布尔类型,true和false,具体作用不明,官网解释:
      Whether to use suffix pattern match for registered file extensions only when matching patterns to requests.If enabled, a controller method mapped to "/users" also matches to "/users.json" assuming ".json" is a file extension registered with the provided ContentNegotiationManager. This can be useful for allowing only specific URL extensions to be used as well as in cases where a "." in the URL path can lead to ambiguous interpretation of path variable content, (e.g. given "/users/{user}" and incoming URLs such as "/users/john.j.joe" and "/users/john.j.joe.json").
      If enabled, this attribute also enables suffix-pattern. The default value is false.
  1. path-matcher元素:我们自定义的地址匹配PathMatcher的实现,如果我们不配置,默认的实现是AntPathMatcher
  2. path-helper元素:我们自定义的用于解析路径匹配的UrlPathHelper的实现,默认的是UrlPathHelper。

    




6.1.10 mvc:message-converters子标签

  该标签表示配置Spring的消息转换器。我们都使用过@RequestBody和@ResponseBody这两个注解,当使用RequestBody注解,对请求的数据进行对象映射时,Spring会根据Request对象header部分的content-Type类型,选择合适的HttpMessageConverter来读取数据;而ResponseBody,则是在进行响应时,同样选择合适的HttpMessageConverter来进行转换,返回对应格式的数据。

  假如我们通过RequestBody注解定义一个对象,来接收前台传入的json参数时,有的时候可能会由于属性的不匹配出现400错误,这时候,我们就可以自定义HttpMessageConverter来完成我们的参数匹配。具体的实例可参考:SpringMVC自定义配置消息转换器踩坑总结

该标签有一个参数:register-defaults,表示除了我们自定义的之外,是否还使用默认的HttpMessageConverter来处理。布尔类型,默认是true,大多数情况下这个值都是true类型。


    
    
        
    
    
        
            
                application/json;charset=UTF-8
                text/html;charset=UTF-8
            
        
         
    

6.1.11 mvc:async-support子标签

  Spring MVC异步请求的配置选项。一般情况下,在同步请求中,浏览器发起请求,服务器开启一个线程响应,响应完成返回一个值给浏览器,而异步的话返回的一般是Callable对象或者DeferredResult对象,然后后端会通过一个回调线程来处理调用的结果,处理完成后再返回。这里请求线程与后台处理是两个线程,并且Callable对象和DeferredResult对象略有些不同,感兴趣的可以自行搜索一下。

  • default-timeout属性,默认超时时间,单位毫秒,如果不配置,则使用底层实现的默认超时时间,比如Servlet3中Tomcat上的10秒;
  • task-executor属性,线程池配置,默认是使用SimpleAsyncTaskExecutor线程池来执行Callable的代码,不过该线程池不重用任何线程,或者说它每次调用都启动一个新线程,性能不是太高,我们可以使用自定义线程池来实现。
    实现可参考:Spring MVC 异步处理请求,提高程序性能

下面看下该标签下的两个子标签:

  1. mvc:callable-interceptors,异步操作的拦截器处理,我们可以自定义拦截器来处理异步操作过程中的一些问题,拦截的响应对象是Callable,比如说超时了咋滴整等;
    The ordered set of interceptors that intercept the lifecycle of concurrently executed requests, which start after a controller returns a java.util.concurrent.Callable.
  2. mvc:deferred-result-interceptors,和上面这个标签类似,不过该标签拦截的是DeferredResult对象;
    The ordered set of interceptors that intercept the lifecycle of concurrently executed requests, which start after a controller returns a DeferredResult.
6.2 mvc:interceptors标签

Spring MVC中的拦截器的配置,拦截日志,登陆,权限等操作,我们直接来看一下该标签下各元素的使用。

  • path-matcher元素:表示我们可以自定义拦截器路径的匹配规则,默认采用的匹配规则是AntPathMatcher,具有ant风格的路径规则,如?表示任何单字符,*表示0个或多个字符,**表示0个或多个目录。
6.2.1 mvc:interceptor子标签

mvc:interceptors 标签下有三种子标签,也就是有两种类型的配置,其中bean和ref表示拦截所有的请求,而mvc:interceptor则是一种更细粒度的配置,可以自定义拦截的路径和要排除的路径。当有多个拦截器的时候,执行的顺序将按照它们配置的顺序来执行。

  • mvc:mapping,表示要拦截的路径,其中属性path为具体要拦截的路径,ref或bean表示具体实现的拦截器;
  • mvc:exclude-mapping,表示要排除掉不需要拦截的路径;
6.3 mvc:default-servlet-handler标签

  Spring MVC用于处理静态资源的一种方式。为了实现优雅的Rest风格的的方式,我们配置DispatcherServlet的请求路径是一般都是配置为/,这种情况下Spring MVC将会捕获Web容器所有的请求,包括静态资源的请求,然后分发到具体的controller去处理,如果找不到则会出现异常。这种情况下,对于静态资源请求的处理,则显得尤为重要了,而Spring MVC自从3.0之后就提供了两种比较优雅的方式:

  1. 一种是配置mvc:default-servlet-handler,配置之后,Spring MVC上下文中会定义一个DefaultServletHttpRequestHandler,请求进入DispatcherServlet之后,会被分发到各个HandlerMapping进行处理,如果该请求最后处理不了,会交给默认的DefaultServletHttpRequestHandler来进行处理;
  2. 一般Web应用服务器默认的Servlet名称是"default",假如我们的Web应用服务器的默认Servlet名称不是"default",则需要通过default-servlet-name属性显示指定;

而DefaultServletHttpRequestHandler中各个服务器对应的servlet名称如下:

/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish */
private static final String COMMON_DEFAULT_SERVLET_NAME = "default";

/** Default Servlet name used by Google App Engine */
private static final String GAE_DEFAULT_SERVLET_NAME = "_ah_default";

/** Default Servlet name used by Resin */
private static final String RESIN_DEFAULT_SERVLET_NAME = "resin-file";

/** Default Servlet name used by WebLogic */
private static final String WEBLOGIC_DEFAULT_SERVLET_NAME = "FileServlet";

/** Default Servlet name used by WebSphere */
private static final String WEBSPHERE_DEFAULT_SERVLET_NAME = "SimpleFileServlet";
6.4 mvc:resources标签

而另一种处理静态资源的方式就是mvc:resources标签了。mvc:default-servlet-handler标签将静态资源的处理最终是由Spring MVC交给了Web服务器进行处理,而mvc:resources则是由Spring MVC自己处理,并且还可以配置一些简单的优化方式。


  1. location元素:首先, 允许静态资源放在任何地方,如WEB-INF目录下、类路径下等,你甚至可以将JavaScript等静态文件打到JAR包中,通过location属性指定静态资源的位置,当然支持通配符的方式;
  2. cache-period元素:我们可以通过配置该属性指定静态资源在浏览器端的缓存时间,单位是秒,默认是没有缓存。在接收到静态资源的获取请求时,会检查请求头的Last-Modified值,如果静态资源没有发生变化,直接从缓存中取值,提高程序性能;
  3. mapping元素:映射地址,比如当我们要引用/WEB-INF/js/文件夹下的文件时,可以直接引用/javascript/**.js,这样就会去我们的WEB-INF/js/里面去找。也就是说,配置了mapping之后,Spring会做一层映射,然后去映射所对应的location下查找静态资源,因为location的位置不是固定的;
  4. order元素:如果配置了多个mvc:resources,那么可以通过order元素指定过滤查找时的优先级,order值越小优先级越高,默认的order值是:Integer.MAX_VALUE - 1

以上静态资源的问题都是基于我们web.xml中配置的url-pattern是拦截全部/的情况。而如果我们的配置是*.do等相关格式的话,就不会有以上相关的问题了。

6.5 mvc:view-controller标签

  对于WEB-INF目录下的页面,我们知道,由于安全性的问题我们无法直接通过URL访问到,一般都是通过在控制器中使用转发的方式来进行访问。而有一些时候我们如果单纯的只是想访问该目录下的页面,并没有一些逻辑操作的时候,可以通过配置该标签将要访问的URL与相应的视图进行映射,不用再通过控制器就可以解析为对应的视图。

 
  1. path参数,是要访问的URL,比如localhost:8080/test
  2. view-name参数,要映射的文件的路径,比如某一个jsp的文件路径是WEB-INF/hello/hello.jsp,那对应的view-name则就是hello/hello,不过不要忘记配置视图解析器。另外,view-name的另外一种方式是重定向的方式:<... view-name="redirect:/admin/index">,有兴趣的可以尝试一下。

总结

到这里,Spring MVC命名空间下的主要标签都学习完了。MVC下的标签针对的是Http请求过程中的各种配置,了解了这些配置,可以让我们在写Web相关的接口的时候更加游刃有余。

本文主要参考资料:官网资料及StackOverFlow网站

你可能感兴趣的:([spring]applicationContext.xml-mvc标签)