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();
    }
}

 

posted on 2016-04-14 10:22  菜鸟的春天  阅读(3790)  评论(0编辑  收藏  举报

导航