文章出處

resteasy 是java體系中比較成熟的rest框架,也是jax-rs規范的實現之一,dubbox的REST服務框架,就是采用的resteasy實現,近日在實際項目中遇到了幾個問題,記錄于此:
 
一、如何用fastjson替換默認的jackson
 
默認情況下,resteasy使用jacksonjaxb來實現json及xml格式的序列化。應用啟動時,會自動掃描帶@Provider的包,找到最合適的provider。fastjson也提供了jax-rs的Provider實現,如果希望使用fastjson來替換默認的jackson,可以按如下步驟操作:
 
1.1、去掉默認的jackson-provider以及jaxb-provider依賴
即:
//    compile 'org.jboss.resteasy:resteasy-jackson-provider:3.0.14.Final'
// compile 'org.jboss.resteasy:resteasy-jaxb-provider:3.0.16.Final'
把這二個依賴jar包去掉,同時記得添加最新的fastjson依賴(1.2.9+版本)
 
1.2、修改web.xml
 1 <web-app id="WebApp_ID" version="2.4"
 2          xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
 4     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
 5     <display-name>Restful Web Application</display-name>
 6 
 7     <context-param>
 8         <param-name>resteasy.resources</param-name>
 9         <param-value>com.cnblogs.yjmyzz.ProductService</param-value>
10     </context-param>
11 
12     <context-param>
13         <param-name>resteasy.scan.providers</param-name>
14         <param-value>false</param-value>
15     </context-param>
16 
17     <context-param>
18         <param-name>resteasy.providers</param-name>
19         <param-value>com.alibaba.fastjson.support.jaxrs.FastJsonProvider</param-value>
20     </context-param>
21 
22     <listener>
23         <listener-class>
24             org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
25         </listener-class>
26     </listener>
27 
28     <servlet>
29         <servlet-name>resteasy-servlet</servlet-name>
30         <servlet-class>
31             org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
32         </servlet-class>
33     </servlet>
34 
35     <servlet-mapping>
36         <servlet-name>resteasy-servlet</servlet-name>
37         <url-pattern>/*</url-pattern>
38     </servlet-mapping>
39 
40 </web-app>

解釋一下:

resteasy.scan.providers:false 是為了防止resteasy自動掃描@Provider的類

resteasy.providers:com.alibaba.fastjson.support.jaxrs.FastJsonProvider 這里指定了使用fastjson來解析json.

 
二、輸出非UTF-8編碼格式的問題
默認情況下,fastjson是采用UTF-8的,詳情見 com.alibaba.fastjson.support.config.FastJsonConfig#FastJsonConfig 源碼
 1     public FastJsonConfig() {
 2 
 3         this.charset = Charset.forName("UTF-8");
 4 
 5         this.serializeConfig = SerializeConfig.getGlobalInstance();
 6         this.parserConfig = new ParserConfig();
 7 
 8         this.serializerFeatures = new SerializerFeature[0];
 9         this.serializeFilters = new SerializeFilter[0];
10         this.features = new Feature[0];
11     }

所以,就算在REST服務的Procuces里指定了其它編碼也沒用

@Path("/product")
@Produces({"application/json; charset=GBK"})
public class ProductService {
    //...
}

解決辦法:又到了我大OOP出場的時候

package com.cnblogs.yjmyzz;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;

import java.nio.charset.Charset;

/**
 * Created by 菩提樹下的楊過(http://yjmyzz.cnblogs.com/) on 2017/4/24.
 */
public class FastJsonConfigGBK extends FastJsonConfig {

    public FastJsonConfigGBK() {
        super();
        setCharset(Charset.forName("GBK"));
        setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
    }
}

從FastJsonConfig派生出一個默認編碼為GBK的子類FastJsonConfigGBK,然后再來一個

package com.cnblogs.yjmyzz;

import com.alibaba.fastjson.support.jaxrs.FastJsonProvider;

/**
 * Created by 菩提樹下的楊過(http://yjmyzz.cnblogs.com/) on 2017/4/24.
 */
public class FastJsonProviderGBK extends FastJsonProvider {

    public FastJsonProviderGBK() {
        super();
        setFastJsonConfig(new FastJsonConfigGBK());
    }
}

最后在web.xml中,參考下面調整:

    <context-param>
        <param-name>resteasy.providers</param-name>
        <param-value>com.cnblogs.yjmyzz.FastJsonProviderGBK</param-value>
    </context-param>

大功告成。

 
三、405 Method Not Allowed無響應信息的處理
resteasy有一套默認的異常處理機制,但默認情況下并未處理405狀態的異常,見下表:
ExceptionHTTP CodeDescription
ReaderException 400 All exceptions thrown from MessageBodyReaders are wrapped within this exception. If there is no ExceptionMapper for the wrapped exception or if the exception isn't a WebApplicationException, then resteasy will return a 400 code by default.
WriterException 500 All exceptions thrown from MessageBodyWriters are wrapped within this exception. If there is no ExceptionMapper for the wrapped exception or if the exception isn't a WebApplicationException, then resteasy will return a 400 code by default.
o.j.r.plugins.providers.jaxb.JAXBUnmarshalException 400 The JAXB providers (XML and Jettison) throw this exception on reads. They may be wrapping JAXBExceptions. This class extends ReaderException
o.j.r.plugins.providers.jaxb.JAXBMarshalException 500 The JAXB providers (XML and Jettison) throw this exception on writes. They may be wrapping JAXBExceptions. This class extends WriterException
ApplicationException N/A This exception wraps all exceptions thrown from application code. It functions much in the same way as InvocationTargetException. If there is an ExceptionMapper for wrapped exception, then that is used to handle the request.
Failure N/A Internal Resteasy. Not logged
LoggableFailure N/A Internal Resteasy error. Logged
DefaultOptionsMethodException N/A If the user invokes HTTP OPTIONS and no JAX-RS method for it, Resteasy provides a default behavior by throwing this exception
所以,如果有一個方法,僅允許POST提交,但是用GET請求來訪問時,沒有任何響應,包括錯誤碼,大多數情況下這不是問題,但是如何用一些url監管系統來檢測url是否可訪問時,由于沒有任何響應,會認為該url無效。
解決辦法:自己定義異常處理ExceptionHandler,參考以下代碼:
 1 package com.cnblogs.yjmyzz;
 2 
 3 import javax.ws.rs.NotAllowedException;
 4 import javax.ws.rs.core.Response;
 5 import javax.ws.rs.ext.ExceptionMapper;
 6 import javax.ws.rs.ext.Provider;
 7 
 8 /**
 9  * Created by yangjunming on 2017/4/26.
10  */
11 @Provider
12 public class RestExceptionHandler implements ExceptionMapper<NotAllowedException> {
13 
14     @Override
15     public Response toResponse(NotAllowedException e) {
16         Response response = Response.status(Response.Status.METHOD_NOT_ALLOWED).entity(e.getMessage()).build();
17         response.getHeaders().add("Content-Type", "text/plain");
18         return response;
19     }
20 }

然后在web.xml把這個加上

1     <context-param>
2         <param-name>resteasy.providers</param-name>
3         <param-value>com.cnblogs.yjmyzz.FastJsonProviderGBK,com.cnblogs.yjmyzz.RestExceptionHandler</param-value>
4     </context-param>

 

參考文章:
http://docs.jboss.org/resteasy/docs/3.1.2.Final/userguide/html_single/#builtinException

文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()