resteasy经验谈

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状态的异常,见下表:

Exception

HTTP Code

Description

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java:如何用代码控制H2 Database启动

    1、纯手动start/stop 1 package com.cnblogs.yjmyzz.h2; 2 3 import java.sql.Connect...

    菩提树下的杨过
  • .net中使用oracle数据库分页的土办法

    近日公司一网站项目,要调用其它系统(call center系统)的oracle数据库数据,只能连接查询,无法创建存储过程,所以只能在sql语句上动脑筋实现分页:...

    菩提树下的杨过
  • silverlight + wcf(json格式) + sqlserver存储过程分页

    silverlight并没有提供现成的分页控件,百度了一圈,也没有发现aspx中好用的类似AspNetPager成熟控件,网上现有的一些分页代码,很多也是基于1...

    菩提树下的杨过
  • C#操作XML的通用方法总结

        在.net的项目开发中,经常会对XML文件进行操作,由于XML文件可以实现跨平台传输,较多的应用在数据传输中,特总结以下几种常用的XML操作方法: ...

    彭泽0902
  • 碎片化 | 第四阶段-36-struts-spring结合jdbc实现删除功能-视频

    如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/z05669dznu6.html ---- 结合jdbc实现删除功能(...

    码神联盟
  • PHP如何上传文件和下载,你学会了吗?

    ​ 在 B/S 程序中文件上传已经成为一个常用功能。其目的是客户可以通过浏览器(Browser)将文件上传到服务器(Server)上的指定目录。

    叫我可儿呀
  • C#zip压缩类

    改造了网上的代码,可以压缩文件夹、指定文件列表(文件和文件夹的混合列表,需要指定子文件夹下需要压缩的文件),注释很详细不做解释

    用户6362579
  • RDLC(Reportview)报表直接打印,支持所有浏览器,客户可在linux下浏览使用

    最近在做一个打印清单的,但是rdlc报表自带的工具栏中的打印按钮只有在ie内核下的浏览器才可以使用(其他的就会 隐藏),这导致了使用火狐和谷歌浏览器还有使用li...

    冰封一夏
  • 测试开发进阶(二十九)

    rest_framework.generics.ListCreateAPIView

    zx钟
  • 一分钟学会在JavaWeb项目中配置数据源

    剽悍一小兔

扫码关注云+社区

领取腾讯云代金券