dubbx雖然是基於jboss的resteasy實現restfull,可是對resteasy原生的配置卻不支持(多是考慮到dubbo本事的設計模式及實現難度,可是和大部分framework的設計風格背道而馳),ExceptionMapper , Filter 和 Interceptor 須要配置在 <dubbo:protocol extension="x,x"/> ,參考 http://dangdangdotcom.github.io/dubbox/rest.htmlhtml
一.Filterjava
Filter主要用於訪問和設置HTTP請求和響應的參數、URI等等。例如,設置HTTP響應的cache headergit
1.ContainerRequestFilter 服務器端請求處理以前,通常用於取請求參數作一些處理,好比記錄access log,流量控制,權限校驗 等。github
經常使用的幾個點:web
使用 @Context 獲取 HttpServletRequest 等servlet內置對象。spring
和標準的web filter同樣,Spring @Autowired 沒法使用,必須經過 WebApplicationContext 獲取Spring管理的bean。apache
數據傳遞使用 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 restful
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(); } }