天天看點

Spring4.1新特性——Spring MVC增強

spring 4.1對spring mvc部分做的增強是最多的,提供了一些視圖解析器的mvc标簽實作簡化配置、提供了groovywebapplicationcontext用于groovy web內建、提供了gson、protobuf的httpmessageconverter、提供了對groovy-templates模闆的支援、jsonp的支援、對jackson的@jsonview的支援等。

1、groovywebapplicationcontext 

2、視圖解析器标簽

之前我們都是這樣定義視圖解析器:

Spring4.1新特性——Spring MVC增強

<bean id="mvcvelocityengine" class="org.springframework.web.servlet.view.velocity.velocityconfigurer">  

    <property name="resourceloaderpath" value="/web-inf/vm/,classpath:com/github/zhangkaitao" />  

</bean>  

<bean id="viewresolver" class="org.springframework.web.servlet.view.velocity.velocityviewresolver">  

    <property name="prefix" value=""/>  

    <property name="suffix" value=".vm"/>  

    <property name="cache" value="false"/>  

而現在我們可以使用mvc标簽定義: 

Spring4.1新特性——Spring MVC增強

<mvc:velocity-configurer resource-loader-path="/web-inf/vm/,classpath:com/github/zhangkaitao"/>  

<mvc:view-resolvers>  

    <mvc:velocity cache-views="false" prefix="" suffix=".vm"/>  

</mvc:view-resolvers>  

再來看一個更複雜的例子: 

Spring4.1新特性——Spring MVC增強

<mvc:groovy-configurer resource-loader-path="classpath:templates/" cache-templates="false"/>  

    <mvc:content-negotiation>  

        <mvc:default-views>  

            <bean class="org.springframework.web.servlet.view.json.mappingjackson2jsonview">  

                <property name="jsonpparameternames">  

                    <set>  

                        <value>jsonp</value>  

                        <value>callback</value>  

                    </set>  

                </property>  

            </bean>  

        </mvc:default-views>  

    </mvc:content-negotiation>  

    <mvc:groovy cache-views="false" suffix=".tpl"/>  

mvc:content-negotiation用于定義内容協商的視圖解析器,且内部可以定義預設視圖;然後我們又定義了mvc:velocity和mvc:groovy兩個視圖解析器;它們會按照順序進行解析。另外幾個視圖解析器是:

mvc:freemarker

mvc:bean-name

mvc:jsp

這種方式有一個很大的問題就是隻能做預設配置,如果想自定義其屬性值就搞不定了,估計當時開發的人考慮不全或沒有經驗。

3、控制器标簽

spring 4.1提供了更豐富的控制器标簽:

3.1、重定向視圖控制器标簽

Spring4.1新特性——Spring MVC增強

<mvc:redirect-view-controller  

        path="/redirect"  

        redirect-url="/status"  

        context-relative="true"  

        status-code="301"  

        keep-query-params="true"/>  

3.2、狀态控制器标簽

Spring4.1新特性——Spring MVC增強

<mvc:status-controller path="/status" status-code="200"/>  

3.3、帶狀态的視圖控制器标簽

Spring4.1新特性——Spring MVC增強

<mvc:view-controller path="/error/**" status-code="200"/>  

4、groovy template引擎內建

4.1、spring配置檔案    

Spring4.1新特性——Spring MVC增強

4.2、模闆heelo.tpl

Spring4.1新特性——Spring MVC增強

yieldunescaped '<!doctype html>'  

html {  

  head {  

    title('hello groovy templates')  

  }  

  body {  

      div("hello $user.name")  

}  

具體文法請參考官方文檔。

5、 jackson @jsonview支援 

可以使用@jsonview來分組渲染json資料,按需展示json資料。

5.1、模型

Spring4.1新特性——Spring MVC增強

public class user implements serializable {  

    public static interface onlyidview {}  

    public static interface onlynameview {}  

    public static interface allview extends onlyidview, onlynameview {}  

    @jsonview(onlyidview.class)  

    private long id;  

    @jsonview(onlynameview.class)  

    private string name;    

    ……  

定義了三個視圖:onlyidview、onlynameview和allview。

5.2、控制器

Spring4.1新特性——Spring MVC增強

@restcontroller  

public class jacksonjsonviewcontroller {  

    @requestmapping("/jackson1")  

    @jsonview(user.onlyidview.class)  

    public user test1() {  

        return new user(1l, "zhangsan");  

    }  

    @requestmapping("/jackson2")  

    @jsonview(user.onlynameview.class)  

    public user test2() {  

    @requestmapping("/jackson3")  

    @jsonview(user.allview.class) //可以省略  

    public user test3() {  

使用@jsonview控制渲染哪些資料。

6、jsonp支援  

6.1、mappingjackson2jsonview提供的支援 

Spring4.1新特性——Spring MVC增強

<bean class="org.springframework.web.servlet.view.json.mappingjackson2jsonview">  

    <property name="jsonpparameternames">  

        <set>  

            <value>jsonp</value>  

            <value>callback</value>  

        </set>  

   </property>  

然後通路如http://localhost:8080/json?callback=callback即可得到jsonp響應:callback({"user":{"id":1,"name":"zhangsan"}});。

6.2、對使用httpmessageconverter的@responsebody的支援 

Spring4.1新特性——Spring MVC增強

@order(2)  

@controlleradvice(basepackages = "com.github")  

public class jsonpadvice extends abstractjsonpresponsebodyadvice {  

    public jsonpadvice() {  

        super("callback", "jsonp"); //指定jsonpparameternames  

通路http://localhost:8080/jackson1?callback=callback即可看到jsonp響應。 

6.3、responsebodyadvice

我們之前實作的jsonpadvice其繼承自abstractjsonpresponsebodyadvice,而abstractjsonpresponsebodyadvice繼承自responsebodyadvice,其作用是在響應體寫出之前做一些處理: 

Spring4.1新特性——Spring MVC增強

@order(1)  

public class myresponsebodyadvice implements responsebodyadvice<object> {  

    @override  

    public boolean supports(methodparameter methodparameter, class<? extends httpmessageconverter<?>> convertertype) {  

        return methodparameter.getmethod().getreturntype().isassignablefrom(user.class);  

    public object beforebodywrite(  

            object obj, methodparameter methodparameter, mediatype mediatype,  

            class<? extends httpmessageconverter<?>> convertertype,  

            serverhttprequest serverhttprequest, serverhttpresponse serverhttpresponse) {  

        user user = ((user)obj);  

        user.setname("---" + user.getname() + "---");  

        return user;  

1、supports指定支援哪些類型的方法進行處理,此處是傳回值為user的;2、我們得到user對象然後在名字前後拼上”---“ ;3、可以指定多個responsebodyadvice,使用@order指定順序。通路http://localhost:8080/jackson2?callback=callback可以看到效果。

7、gson httpmessageconverter

7.1、spring配置 

Spring4.1新特性——Spring MVC增強

<mvc:annotation-driven>  

    <mvc:message-converters>  

        <bean class="org.springframework.http.converter.json.gsonhttpmessageconverter"/>  

    </mvc:message-converters>  

</mvc:annotation-driven>  

使用方式和jackson json類似。本文使用的是<gson.version>2.2.4</gson.version>版本。

8、protobuf httpmessageconverter

8.1、spring配置 

Spring4.1新特性——Spring MVC增強

        <bean class="org.springframework.http.converter.protobuf.protobufhttpmessageconverter">  

            <constructor-arg>  

                <bean class="com.github.zhangkaitao.web.controller.myextensionregistryinitializer"/>  

            </constructor-arg>  

        </bean>  

8.2、定義protobuf message(proto/user.proto)

Spring4.1新特性——Spring MVC增強

package com.github.zhangkaitao.pb;  

 option java_package = "com.github.zhangkaitao.pb";  

 option java_outer_classname = "userprotos";  

 message user {  

   optional int64 id = 1;  

   optional string name = 2;  

 }  

8.3、添加maven插件自動把protobuf message轉化成java代碼

Spring4.1新特性——Spring MVC增強

<plugin>  

    <groupid>com.google.protobuf.tools</groupid>  

    <artifactid>maven-protoc-plugin</artifactid>  

    <version>0.1.10</version>  

    <executions>  

        <execution>  

            <id>generate-sources</id>  

            <goals>  

                <goal>compile</goal>  

            </goals>  

            <phase>generate-sources</phase>  

            <configuration>  

                <protosourceroot>${basedir}/src/main/proto/</protosourceroot>  

                <includes>  

                    <param>**/*.proto</param>  

                </includes>  

            </configuration>  

        </execution>  

    </executions>  

    <configuration>  

        <protocexecutable>d:/software/protoc.exe</protocexecutable>  

    </configuration>  

</plugin>  

8.4、測試控制器 

Spring4.1新特性——Spring MVC增強

public class protobufcontroller {  

    @requestmapping("/proto/read")  

    public responseentity<userprotos.user> protoread() {  

        return responseentity.ok(userprotos.user.newbuilder().setid(1).setname("zhangsan").build());  

    @requestmapping("/proto/write")  

    public responseentity<userprotos.user> protoread(requestentity<userprotos.user> requestentity) {  

        system.out.println("server===\n" + requestentity.getbody());  

        return responseentity.ok(requestentity.getbody());  

8.5、測試用例(com.github.zhangkaitao.proto.prototest)   

Spring4.1新特性——Spring MVC增強

@test  

public void testread() {  

    httpheaders headers = new httpheaders();  

    requestentity<userprotos.user> requestentity =  

            new requestentity<userprotos.user>(headers, httpmethod.post, uri.create(baseuri + "/proto/read"));  

    responseentity<userprotos.user> responseentity =  

            resttemplate.exchange(requestentity, userprotos.user.class);  

    system.out.println(responseentity.getbody());  

public void testwrite() {  

    userprotos.user user = userprotos.user.newbuilder().setid(1).setname("zhangsan").build();  

            new requestentity<userprotos.user>(user, headers, httpmethod.post, uri.create(baseuri + "/proto/write"));  

測試過程中會抛出:

Spring4.1新特性——Spring MVC增強

caused by: java.lang.unsupportedoperationexception  

    at java.util.collections$unmodifiablemap.put(collections.java:1342)  

    at org.springframework.http.httpheaders.set(httpheaders.java:869)  

    at org.springframework.http.converter.protobuf.protobufhttpmessageconverter.setprotoheader(protobufhttpmessageconverter.java:196)  

這是因為protobufhttpmessageconverter會修改響應頭,但是responseentity構造時httpheaders是不允許修改的。暫時解決辦法是注釋掉:

Spring4.1新特性——Spring MVC增強

//setprotoheader(outputmessage, message);  

9、requestentity/responseentity

spring 4.1提供了responseentity配對的requestentity,使用方式和httpentity一樣。具體可以參考com.github.zhangkaitao.web.controller.requestresponseentitycontroller。

10、mvcuricomponentsbuilder

Spring4.1新特性——Spring MVC增強

public class mvcuricomponentsbuildercontroller {  

    @requestmapping("/uri")  

    public string mvcuricomponentsbuilder1() {  

        return mvcuricomponentsbuilder.frommappingname("mucbc#mvcuricomponentsbuilder1").build();  

    @requestmapping("/uri/{id}")  

    public string mvcuricomponentsbuilder2(@pathvariable long id) {  

        return mvcuricomponentsbuilder.frommappingname("mucbc#mvcuricomponentsbuilder2").arg(0, "123").build();  

規則是“控制器所有大寫字母#方法名”找到相應的方法。 另外可以直接在頁面中使用如下方式擷取相應的uri:

Spring4.1新特性——Spring MVC增強

${s:mvcurl('mucbc#mvcuricomponentsbuilder2').arg(0,"123").build()}  

11、mockrestserviceserver

12、mockmvcconfigurer

spring 4.1提供了mockmvcconfigurer用于進行一些通用配置,使用方式如下:

Spring4.1新特性——Spring MVC增強

mockmvc = mockmvcbuilders.webappcontextsetup(context).apply(defaultsetup()).build();   

mockmvcconfigurer實作: 

Spring4.1新特性——Spring MVC增強

private mockmvcconfigurer defaultsetup() {  

    return new mockmvcconfigurer() {  

        @override  

        public void afterconfigureradded(configurablemockmvcbuilder<?> configurablemockmvcbuilder) {  

            configurablemockmvcbuilder.alwaysexpect(status().isok());  

        }  

        public requestpostprocessor beforemockmvccreated(configurablemockmvcbuilder<?> configurablemockmvcbuilder, webapplicationcontext webapplicationcontext) {  

            return new requestpostprocessor() {  

                @override  

                public mockhttpservletrequest postprocessrequest(mockhttpservletrequest mockhttpservletrequest) {  

                    mockhttpservletrequest.setattribute("aa", "aa");  

                    return mockhttpservletrequest;  

                }  

            };  

    };  

可以在如上實作中進行一些通用配置,如安全(往request中扔安全對象之類的)。測試用例可參考com.github.zhangkaitao.proto.prototest2。

本文轉自http://jinnianshilongnian.iteye.com/blog/2107205