【SpringMVC】根据请求处理资源表述

通常一个web应用中,资源都在浏览器中以HTML的形式表述。
但对于一个RESTful的资源应以多种形式表述,用户要求什么就以什么样的形式表述。
比如HTML、XML、JSON、PDF、EXCEL...

Spring有两种方式处理表述形式:
·org.springframework.web.servlet.view.ContentNegotiatingViewResolver
·org.springframework.http.converter.HttpMessageConverter

一、ContentNegotiatingViewResolver

虽然也是ViewResolver一族的,但他并不解析视图,而是解析视图的任务委托给其他ViewResolver。
默认情况下会从所有ViewResolver中自动选择合适的ViewResolver,但为了更明确的表述,我们会选择使用setViewResolvers(List<ViewResolver> viewResolvers)更明确地定义ViewResolver。
ContentNegotiatingViewResolver委托所有viewResolvers解析视图后将视图存放在待选视图列表(candidateViews)中,如果设置了defaultView,默认视图会在列表的尾部。

如何确定请求的媒体类型? 虽然accept header里也可以获得请求的表述形式,但ContentNegotiatingViewResolver会先考虑URL后面的扩展名。
从扩展名无法得到类型时将考虑accept header。如果此时仍然无法获得有效的类型,将使用defaultContentType设置(先已在ContentNegotiatingViewResolver中deprecated,可以在org.springframework.web.accept.ContentNegotiationManagerFactoryBean中看到)。
我们可以自定义扩展名和媒体类型映射。
看一些书和一些博客直接使用了ContentNegotiatingViewResolver的setMediaTypes(Map<String, String> mediaTypes),但值得注意的是,这个方法已经deprecated了(当然,与之有关的一系列setFavorPathExtension、setFavorParameter、setIgnoreAcceptHeader什么的都deprecated了,但他们都移到了ContentNegotiationManager中)。
现在建议使用setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager),但并不复杂,只是变得更加OO而已。
另外org.springframework.web.accept.ContentNegotiationManagerFactoryBean是ContentNegotiationManager的:
A factory providing convenient access to a {@code ContentNegotiationManager} configured with one or more {@link ContentNegotiationStrategy} instances.

配置contentNegotiationMananger:

<bean id="contentNegotiationManager"
    class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorParameter" value="true" />
    <property name="parameterName" value="format" />
    <property name="ignoreAcceptHeader" value="false" />
    <property name="mediaTypes">
        <value>
            json=application/json
            xml=application/xml
        </value>
    </property>
    <property name="defaultContentType" value="text/html" />
</bean>

话说favorPathExtension默认就是true,因此在这里就不做设置了。
favorPathExtension为false则勿略扩展名。
favorParameter与parameterName是一对属性。
favorParameter设置为true可以用[?format=表述形式]这种方式。
默认值是format,这个值可以通过parameterName来设置。
ignoreAcceptHeader默认为false,即不忽略Accept信息。

配置ContentNegotiatingViewResolver:

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name= "contentNegotiationManager" ref= "contentNegotiationManager"/>
<!--         <property name="mediaTypes"> -->
<!--             <map> -->
<!--                 <entry key="atom" value="application/atom+xml" /> -->
<!--                 <entry key="html" value="text/html" /> -->
<!--                 <entry key="json" value="application/json" /> -->
<!--             </map> -->
<!--         </property> -->
        <property name="viewResolvers">
            <list>
<!--                 <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> -->
                <bean
                    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="prefix" value="/WEB-INF/views/" />
                    <property name="suffix" value=".jsp" />
                </bean>
            </list>
        </property>
        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
            </list>
        </property>
    </bean>

ContentNegotiatingViewResolver的setMediaTypes没deprecated时是想上面那样写的,现在都写到contentNegotiationMananger了。

二、HttpMessageConverter

通常可以看到把对象放到Model中在View中渲染。使用HttpMessageConverter则可以将方法返回的对象转为要求的表述形式。

上面是实现类,很多都是自动注册的。
org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport

protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
    StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
    stringConverter.setWriteAcceptCharset(false);
    messageConverters.add(new ByteArrayHttpMessageConverter());
    messageConverters.add(stringConverter);
    messageConverters.add(new ResourceHttpMessageConverter());
    messageConverters.add(new SourceHttpMessageConverter<Source>());
    messageConverters.add(new AllEncompassingFormHttpMessageConverter());
    if (romePresent) {
        messageConverters.add(new AtomFeedHttpMessageConverter());
        messageConverters.add(new RssChannelHttpMessageConverter());
    }
    if (jaxb2Present) {
        messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
    }
    if (jackson2Present) {
        messageConverters.add(new MappingJackson2HttpMessageConverter());
    }
    else if (jacksonPresent) {
        messageConverters.add(new org.springframework.http.converter.json.MappingJacksonHttpMessageConverter());
    }
}

另外我们需要用到@ResponseBody,以表示Controller的返回值会绑定在响应体中,并将其转换为客户端请求的表述形式。
请求的表述形式主要是Accept头信息,如果请求中不包括Accept头信息则会假设可以接受任何表述形式。当然,如果在方法的@RequestMapping中设置了Accept头信息则只会处理包含这些Accept信息的请求。

比如下面的代码中我要将User数组转为JSON形式表述:

@RequestMapping(value ="/userList",headers={"Accept="+MediaType.APPLICATION_JSON_VALUE})
public @ResponseBody User[] queryUserList(){
    User[] u = new User[4];
    u[0] = new User("0001","King","t;stmdtkg");
    u[1] = new User("0001","King","t;stmdtkg");
    u[2] = new User("0001","King","t;stmdtkg");
    u[3] = new User("0001","King","t;stmdtkg");
    return u;
}

@ResponseBody对应,我们也可以使用@RequestBody
比如client端请求时以JSON格式传递参数,我在Controller方法的某个参数前加上@ResponseBody User user则转换为User类型。

另外,注册一个MessageConverter的方式非常简单。

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="pac.king.common.MessageConverter" />
    </mvc:message-converters>
</mvc:annotation-driven>

【SpringMVC】根据请求处理资源表述

时间: 2024-12-08 13:57:41

【SpringMVC】根据请求处理资源表述的相关文章

【SpringMVC】静态资源访问的问题

在项目中经常会用到一些静态的资源,而一般我们在配置SpringMVC时会让SpringMVC接管所有的请求(包括静态资源的访问), 那么我们怎样才能最简单的来配置静态资源的访问呢? 一,在web.xml中让SpringMVC接管所有请求 如图 二,在SpringMVC中配置静态资源映射路径 这句话的意思是将ccc这个文件夹的访问路径映射为javaScript 也就是说 我们在地址栏里面访问JavaScript下的某个图片,其实经过SpringMVC的处理后,访问的是ccc下的文件 例如我们要访问

SpringMVC访问静态资源

转自:SpringMVC访问静态资源 在SpringMVC中常用的就是Controller与View.但是我们常常会需要访问静态资源,如html,js,css,image等. 默认的访问的URL都会被DispatcherServlet所拦截,但是我们希望静态资源可以直接访问.该肿么办呢? 在配置文件:web.xml可以看到: <!-- Processes application requests --> <servlet> <servlet-name>appServle

【SpringMVC】SpringMVC访问静态资源

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文要以一个例子来说明SpringMVC访问静态资源 <mvc:resources 的使用方法:<!--对静态资源文件的访问--> <mvc:resources mapping="/images/**" location="/images/" /> /images /**映射到 ResourceHttpRequestHandler

SpringMVC拦截静态资源的处理办法

SpringMVC拦截静态资源导致  JS  CSS  无法加载  可以在配置文件中加入以下代码 <mvc:resources location="/statices/" mapping="/statices/**"/> //JS CSS 等文件 <mvc:resources location="/pages/" mapping="/pages/**"/> //Html页面

SpringMVC 处理静态资源

SpringMVC找不到静态资源: 1. 为什么会有这样的问题: 优雅的 REST 风格的资源URL 不希望带 .html 或 .do 等后缀 若将 DispatcherServlet 请求映射配置为 /, 则 Spring MVC 将捕获 WEB 容器的所有请求, 包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理, 因找不到对应处理器将导致错误. 2. 解决: 在 SpringMVC 的配置文件中配置 <mvc:default-servlet-handler/>

解决SpringMVC拦截静态资源的问题

优雅REST风格的资源URL不希望带 .html 或 .do 等后缀.由于早期的Spring MVC不能很好地处理静态资源,所以在web.xml中配置DispatcherServlet的请求映射,往往使用 *.do . *.xhtml等方式.这就决定了请求URL必须是一个带后缀的URL,而无法采用真正的REST风格的URL. 如果将DispatcherServlet请求映射配置为"/",则Spring MVC将捕获Web容器所有的请求,包括静态资源的请求,Spring MVC会将它们当

EasyUI + SpringMVC 解决静态资源访问

我们的项目用的是EasyUI+SpringMVC+EJB+JPA,分享一下项目中遇到的一些问题及其解决方法.前台用的EasyUI,页面中引入了easyUI的js与css(引入路径正确),但是无论如何都显示不出来,如下图: EasyUI的样式没有,看控制台:警告,找不到 21:26:25,643 WARN [org.springframework.web.servlet.PageNotFound](http-localhost/127.0.0.1:8080-1) No mapping found

SpringMVC访问静态资源的三种方式

如何你的DispatcherServlet拦截 *.do这样的URL,就不存在访问不到静态资源的问题.如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对*.js,*.jpg的访问也就被拦截了. 方案一:激活Tomcat的defaultServlet来处理静态文件 1 <servlet-mapping> 2 <servlet-name>default</servlet-name> 3 <url-pattern>*.jpg</u

SpringMVC请求静态资源

在SpringMVC配置文件中增加如下配置 <!-- default-servlet-handler 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler, 它会对进入 DispatcherServlet 的请求进行筛查, 如果发现是没有经过映射的请求, 就将该请求交由 WEB 应用服务器默认的 Servlet 处理. 如果不是静态资源的请求,才由 DispatcherServlet 继续处理 一般 WEB 应用服务器默认的 Servlet