Jersey学习记录(三)--过滤拦截器与异常处理
来源:互联网 发布:trigger知乎 编辑:程序博客网 时间:2024/05/04 06:38
本文记录全局异常返回,过滤器,拦截器.
一.全局异常处理器
webservice定义全局返回错误码是很重要的一个功能,jersey正好就能实现这一功能.
整个流程就是当jersey托管的类发现了异常,抛出给jersey的异常处理器,该异常处理器直接返回自定义的错误代码.
1.定义异常代码
可以使用枚举类,也可以写到配置文件中,再写个工具类获取.看项目需求了.
public enum ErrorCode { OK(0,"OK"),ID_INVALID(1,"ID is invalid"),OTHER_ERR(2,"未知错误"); private int code; private String message; ErrorCode(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; }}
2.定义出现异常将返回的实体代理
也就是封装异常信息到这个类中,再转换为json串返回,如果自己直接构造字串也是可以代替的
@XmlRootElement//标识该资源可以被jersey转为json或者xmlpublic class ErrorEntity { private int resp_code; private String resp_msg; public ErrorEntity(int resp_code, String resp_msg) { this.resp_code = resp_code; this.resp_msg = resp_msg; } public ErrorEntity() { } public int getResp_code() { return resp_code; } public void setResp_code(int resp_code) { this.resp_code = resp_code; } public String getResp_msg() { return resp_msg; } public void setResp_msg(String resp_msg) { this.resp_msg = resp_msg; }}
3.自定义异常
自定义异常,处理时拦截该指定异常
public class DeviceException extends Exception { private int code; private String message; /** * 构造异常类 * @param code * @param message */ public DeviceException( int code,String message) { this.code = code; this.message = message; } /** * 根据枚举类构造异常结果 * @param errorCode */ public DeviceException(ErrorCode errorCode) { this.code = errorCode.getCode(); this.message = errorCode.getMessage(); } public int getCode() { return code; } public void setCode(int code) { this.code = code; } @Override public String getMessage() { return message; } public void setMessage(String message) { this.message = message; }}
4.定义jersey异常处理器
异常处理器要实现ExceptionMapper<Exception>
接口,并复写返回方法,另外一定要使用@Provider标识该类为一个jersey的’处理器’,如下:
@Providerpublic class DeviceExceptionMapper implements ExceptionMapper<Exception> { @Override public Response toResponse(Exception e) { Response.ResponseBuilder ResponseBuilder = null; if (e instanceof DeviceException){ //截取自定义类型 DeviceException exp = (DeviceException) e; ErrorEntity entity = new ErrorEntity(exp.getCode(),exp.getMessage()); ResponseBuilder = Response.ok(entity, MediaType.APPLICATION_JSON); }else { ErrorEntity entity = new ErrorEntity(ErrorCode.OTHER_ERR.getCode(),e.getMessage()); ResponseBuilder = Response.ok(entity, MediaType.APPLICATION_JSON); } System.out.println("执行自定义异常"); return ResponseBuilder.build(); }}
5.注册该异常
在RESTApplication中要加载该异常,可以使用package扫包,或者直接注册异常都是可以的.
public class RESTApplication extends ResourceConfig { public RESTApplication() { //想让jersey托管的部分需要加入扫描,或者使用register指定托管类也可以 packages("com.haikong.resources","com.haikong.exception"); //加载日志包 register(LoggingFilter.class); //加载json转换器 register(JacksonJsonProvider.class); System.out.println("加载RESTApplication"); }}
6.测试
写一个请求链接,该请求直接抛出其他异常
/** * 测试全局异常托管 * @throws DeviceException */ @GET @Path("/testexception") public void testException() throws DeviceException { if (true){ throw new DeviceException(ErrorCode.OTHER_ERR); } }
到此异常处理器完成.
二.过滤器
过滤器可以修改入站和出站请求和响应包括标题的修改,实体等的请求/响应参数。例如用来操纵请求和响应参数像HTTP头,URI和/或HTTP方法.
服务器过滤主要有
ContainerRequestFilterContainerResponseFilter
两个接口,显而易见,一个是过滤请求前,一个是过滤请求后.
1.ContainerResponseFilter
这个是请求结束后响应回复阶段过滤,很简单,有什么参数直接加个断点就能查看到了,同样要使用注解,让jersey认为该类为其一个处理器.
/** * 对于response的过滤器 * 过滤器主要是用来操纵请求和响应参数像HTTP头,URI和/或HTTP方法 * @author Niu Li * @date 2016/7/27 */@Providerpublic class ResponseFilter implements ContainerResponseFilter { @Override public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException { /** * 具体可以获取什么参数,加个断点就可以看到了 */ System.out.println("执行回复过滤"); }}
2.ContainerRequestFilter
对于这个注解有@PreMatching和@Provider,经测试,前者只要收到请求就开始执行,后者是收到请求,匹配到相应的处理方法后执行,也就是前者匹配前,后者匹配后执行.
并且我测试的两个一起用的话,只执行前者,这个不知道哪里有问题,按照官方文档应该是都可以执行的.不太懂了
/** * 对于request的过滤器 * 过滤器主要是用来操纵请求和响应参数像HTTP头,URI和/或HTTP方法 * @author Niu Li * @date 2016/7/27 * Provider //这个是匹配后增加参数或者减少参数 */@PreMatching //不知道为什么和后请求过滤器冲突,不能同时使用public class PreRequestFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext containerRequestContext) throws IOException { /** * 具体可以获取什么参数,加个断点就可以看到了 */ System.out.println("PreRequestFilter"); }}
3.启用
启用同样需要注册RESTApplication,并且@PreMatching这个注解扫包注入并没什么用,只能手动注册该类.原因未知.
public class RESTApplication extends ResourceConfig { public RESTApplication() { //想让jersey托管的部分需要加入扫描,或者使用register指定托管类也可以 packages("com.haikong.resources","com.haikong.exception"); register(LoggingFilter.class); register(JacksonJsonProvider.class); //注册过滤器,扫包对@PreMatching注解无用,只能手动加入 register(PreRequestFilter.class); register(ResponseFilter.class); /** * 对于链接,先执行请求过滤,有异常则执行异常过滤,最后执行回复过滤 */ System.out.println("加载RESTApplication"); }}
测试结果和下一个的拦截器一起测试.
三.拦截器
拦截器意图操纵的实体,通过操纵实体的输入/输出数据流。比如你需要编码的客户端请求的实体主体,
jersey提供如下拦截器:`
ReaderInterceptorWriterInterceptor
reader用的不多,writer可以用来开启gzip压缩,这个倒是很实用,并且jersey开启gzip压缩很方便,乱码问题解决办法就是主动告诉浏览器使用哪一种编码解码就好了
public class GzipInterceptor implements WriterInterceptor { @Override public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { MultivaluedMap<String, Object> headers = context.getHeaders(); headers.add("Content-Encoding", "gzip"); String ContentType = context.getMediaType().toString(); headers.add("Content-Type",ContentType+";charset=utf-8");//解决乱码问题 final OutputStream outputStream = context.getOutputStream(); context.setOutputStream(new GZIPOutputStream(outputStream)); context.proceed(); System.out.println("GZIP拦截器压缩"); }}
同样需要注册该类
//注册拦截器 register(GzipInterceptor.class);
四.执行顺序
还是之前那个抛出异常的方法,访问后先执行请求过滤器,再匹配到相应方法,执行方法体,然后有异常,执行异常拦截器,其次执行回复过滤,最后是GZIP压缩,如下图:
具体执行顺序官方给的很清楚.可以去查看官方文档
参考资料:
https://waylau.gitbooks.io/jersey-2-user-guide/content/
https://jersey.java.net/documentation/latest/
项目示例:
SJM框架整合: https://github.com/nl101531/JavaWEB
- Jersey学习记录(三)--过滤拦截器与异常处理
- C#学习记录三:异常处理
- SpringMVC学习记录(三)--异常处理
- jersey搭建过程的异常与处理
- SpringMVC自定义拦截器与异常处理
- SpringMVC自定义拦截器与异常处理
- Jersey 统一异常处理
- Jersey实现对方法进行过滤拦截
- Jersey拦截器
- 四.SpringMVC中的 拦截器与异常处理
- 统一处理jersey的异常
- Castle AOP拦截与异常处理
- C++异常处理学习记录
- PLSQL学习(三) 异常处理
- SpringMVC拦截器学习记录
- Struts2拦截器实现异常处理机制
- Struts2拦截器实现异常处理机制
- Struts2拦截器实现异常处理机制
- Qt之Threads和QObjects
- Jersey学习记录(一)--环境配置
- Android 项目移植到Android Studio 时出现问题处理
- rapidjson::Document _doc
- Jersey学习记录(二)--请求映射和页面传值
- Jersey学习记录(三)--过滤拦截器与异常处理
- "error while loading shared libraries: xxx.so.x" 错误的原因和解决办法
- STL 之 priority_queue
- ubuntu install software
- HDU 1028 Ignatius and the Princess III
- ObjC的initialize和init
- java几种单例模式写法
- 用JS检测必须填写的字段是否为空(使用了函数嵌套)
- [Android] 修图工具Draw9patch使用小结(附ubuntu快捷截图方法)