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

2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 佐佐木明希大嫂中文字幕全集 善良的小妻子字幕 公公在我洗碗时在厨房要了我 大嫂被肉翻了天佐佐木明希1 教师蕾丝短裙中文字幕 瓜棚里和大嫂乱禽 强睡大嫂中文字 免费 佐佐木明希 房东中文字幕 与父亲干柴烈火 中文字幕丈夫不在 9大嫂被禽翻中文字幕 侵犯你的贞洁 中文字幕 年轻的妻子在线观中文字幕 大嫂被翻天了佐佐木b希中文7 美丽的大嫂中文字幕影迅雷下载 邻居的妻子中文字幕下载 神马电影院电影中文 神马电影院理论中文 女儿的朋友5中文神马电影院 97手机2019电影院专用版中文 厨房里进入朋友的老婆 中文版电影院 神马电影院 中文 儿子的妻子中文字幕 下载 樱桃中文版电影院 大富豪电影院韩国中文 老婆的闺蜜们喝醉了在家 中文潮人影院您手中的电影院 朋友不在晚上去他家干 趁兄弟喝醉上他女朋友在线播放 神马电影院午伦中文 朋友喝醉上其妻 我朋友的妻子韩语中文2018 在朋友家趁朋友喝醉上他老婆 日本朋友的妻子和母亲中文版 偷朋友的妻子在线中文播放 邻居的妻子日本中文2018 朋友的妻子日本中文版7 朋友的妈l妈中文字电影 母亲在美国被黑人证服 妻子报恩献身张局长加强版2