resteasy经验谈

简介: resteasy 是java体系中比较成熟的rest框架,也是jax-rs规范的实现之一,dubbox的REST服务框架,就是采用的resteasy实现,近日在实际项目中遇到了几个问题,记录于此:   一、如何用fastjson替换默认的jackson   默认情况下,resteasy使用jackson和jaxb来实现json及xml格式的序列化。
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
目录
相关文章
|
8月前
|
XML 设计模式 JSON
解密SpringMVC:探秘常用注解,让你的Java应用飞速起航!
解密SpringMVC:探秘常用注解,让你的Java应用飞速起航!
|
11月前
|
前端开发 Java 数据库连接
Spring Framework 6.x强势发布
基于JSR-330的**@Inject注解将在Jakarta.Inject中。 基于JSR-250的注解@PostConstruct和@Predestroy**将在jakarta.annotation。 暂时,Spring也一直检测到其javax等价物,涵盖预编译的二进制二进制文件中的常用使用。 由于jakarta ee迁移,数据访问和事务,请务必使用Hibernate-Core-Jakarta Artifact升级到Hibernate Orm 5.6.x,以及切换您的javax.persistence接口到jakarta.persistence。
184 0
|
12月前
|
负载均衡 监控 算法
探秘SpringCloud系列《序篇:SpringCloud江湖简介》
探秘SpringCloud系列《序篇:SpringCloud江湖简介》
64 0
|
消息中间件 负载均衡 监控
国王小组:搭建交易所开发完整的Spring Cloud框架
关于SpringCloud Spring Cloud是一个有序的框架集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发方式完成 一键启动和部署。Spring Cloud并不重复制造车轮。它只是结合了各家公司开发的成熟实用的服务框架。通过Spring Boot风格的重新封装,屏蔽了复杂的配置和实现原理,最后给开发 作者留下了一套简单易懂、易于部署、易于维护的分布式系统开发套件。一般来说,一个完整的Spring Cloud框架应该是如下图所示。
国王小组:搭建交易所开发完整的Spring Cloud框架
|
JSON Java 编译器
告别BeanUtils,Mapstruct从入门到精通
如果你现在还在使用BeanUtils,看了本文,也会像我一样,从此改用Mapstruct。
973 0
告别BeanUtils,Mapstruct从入门到精通
|
消息中间件 XML JSON
面对Spring Boot 3最低支持Java17如洪水猛兽袭来,何去何从
面对Spring Boot 3最低支持Java17如洪水猛兽袭来,何去何从
面对Spring Boot 3最低支持Java17如洪水猛兽袭来,何去何从
|
缓存 开发框架 Java
如果有人问你 JFinal 如何集成 EhCache,把这篇文章甩给他
废话不多说,就说一句:在 JFinal 中集成 EhCache,可以提高系统的并发访问速度。 可能有人会问 JFinal 是什么,EhCache 是什么,简单解释一下。 JFinal 是一个基于Java 语言的极速 Web 开发框架,用起来非常爽,谁用谁知道。EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干的特点,用起来非常爽,谁用谁知道。 JFinal 本身已经集成了 EhCache 这个缓存插件,但默认是没有启用的。那怎么启用呢? 请随我来。
|
JSON Java API
Swagger 3.0 官方 starter 诞生,野生的可以扔了!
Swagger 3.0 官方 starter 诞生,野生的可以扔了!
3855 0
Swagger 3.0 官方 starter 诞生,野生的可以扔了!
|
负载均衡 Kubernetes 网络协议
阿里雷卷:RSocket从入门到落地,RSocket让AJP换发青春
借助 RSocket 的架构提供,我们可以将之前比较复杂的方案简化,当然最最重要的是性能的提升,即便之前的一些性能提升技术点,可能由于一些约束等,现在和 RSocket 对接,那些问题都不存在啦!这篇文章只是一个架构启发,不会浪费你时间让你学习 20 年前的技术和知识。
17917 1
阿里雷卷:RSocket从入门到落地,RSocket让AJP换发青春
|
SQL 缓存 JSON
悟空 CRM 9.0 发布,高品质 JFinal 开源项目
悟空CRM采用全新的前后端分离模式,本仓库代码中已集成前端vue打包后文件,可免去打包操作 如需调整前端代码,请单独下载前端代码,前端代码在根目录的ux文件夹中 主要技术栈 核心框架:jfinal3.
2573 0