dubbox ExceptionMapper Filter request response 数据获取 数据传递
dubbx虽然是基于jboss的resteasy实现restfull,但是对resteasy原生的配置却不支持(可能是考虑到dubbo本事的设计模式及实现难度,但是和大部分framework的设计风格背道而驰),ExceptionMapper , Filter 和 Interceptor 需要配置在 <dubbo:protocol extension="x,x"/> ,参考 http://dangdangdotcom.github.io/dubbox/rest.html
一.Filter
Filter主要用于访问和设置HTTP请求和响应的参数、URI等等。例如,设置HTTP响应的cache header
1.ContainerRequestFilter 服务器端请求处理之前,一般用于取请求参数做一些处理,比如记录access log,流量控制,权限校验 等。
常用的几个点:
使用 @Context 获取 HttpServletRequest 等servlet内置对象。
和标准的web filter一样,Spring @Autowired 无法使用,必须通过 WebApplicationContext 获取Spring管理的bean。
数据传递使用 SecurityContext (本人能力有限,没找到更好的方式)。
直接返回结果 requestContext.abortWith(response);特别注意,调用此方法后,如果继续有其他code,下边的code一样会执行的。(java语言本身的限制)。
package com.leon.filter; import java.io.IOException; import java.util.Date; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; @Component public class SecurityFilter implements ContainerRequestFilter{ @Context private transient HttpServletRequest servletRequest; private SellerSecurityService sellerSecurityService; private AccessLogService accessLogService; private SellerPvService sellerPvService; @Override public void filter(ContainerRequestContext requestContext) throws IOException { Date now=new Date(); String appKey=HttpUtil.getParameterString(servletRequest,"appkey"); if(StringUtil.isEmpty(appKey)){ Response response=bulidUnauthResponse(Constant.missAppKeyResponse); requestContext.abortWith(response); return; } getService(); AccessLog accessLog=new AccessLog(); accessLogService.log(accessLog); SecurityContext securityContext=bulidSecurityContext("test"); requestContext.setSecurityContext(securityContext); } public static SecurityContext bulidSecurityContext(final String value){ return new SecurityContext() { @Override public boolean isUserInRole(String role) { return false; } @Override public boolean isSecure() { return false; } @Override public Principal getUserPrincipal() { return null; } @Override public String getAuthenticationScheme() { return value; } }; } private Response bulidUnauthResponse(String context){ return Response.ok().status(Constant.unAuthCode).entity(context).build(); } public void getService() { if(sellerSecurityService!=null){ return; } WebApplicationContext wac=WebApplicationContextUtils.getWebApplicationContext(servletRequest.getServletContext()); sellerSecurityService=wac.getBean(SellerSecurityService.class); accessLogService=wac.getBean(AccessLogService.class); sellerPvService=wac.getBean(SellerPvService.class); } }
2.ContainerResponseFilter 请求处理完之后调用,通常用作装入公共信息到 response
public class CacheControlFilter implements ContainerResponseFilter { public void filter(ContainerRequestContext req, ContainerResponseContext res) { if (req.getMethod().equals("GET")) { res.getHeaders().add("Cache-Control", "someValue"); } } }
二.Interceptor
Interceptor主要用于访问和修改输入与输出字节流,例如,手动添加GZIP压缩:
1.ReaderInterceptor 拦截 MessageBodyReader.readFrom 可以用来实现校验
2.WriterInterceptor 拦截 MessageBodyWriter.writeTo 可以用来实现数据压缩
public class GZIPWriterInterceptor implements WriterInterceptor { @Override public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { OutputStream outputStream = context.getOutputStream(); context.setOutputStream(new GZIPOutputStream(outputStream)); context.proceed(); } }
三.ExceptionMapper
用来自定义Exception的处理方式。必须继承 ExceptionMapper<E extends Throwable>,泛型为处理的异常类型
package com.leon.exception; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; import org.apache.log4j.Logger; public class ExceptionMapperSupport implements ExceptionMapper<Exception> { private static final Logger LOGGER = Logger .getLogger(ExceptionMapperSupport.class); /** * 异常处理 * * @param exception * @return 异常处理后的Response对象 */ @Override public Response toResponse(Exception exception){ String response; int code; if(exception instanceof MyException){ MyException myException=(MyException)exception; response="{\"resp_code\":\""+myException.getRespCode()+"\",\"resp_info\":\""+myException.getRespInfo()+"\"}"; code=Constant.successCode; }else{ response=Constant.errorResponse; LOGGER.error(exception.getMessage(), exception); code=Constant.errorCode; } return Response.ok(response, MediaType.APPLICATION_JSON).status(code) .build(); } }