webservice-自定义注解处理参数加解密问题 前一段项目中用到了webservice,正好自己之前也了解过一点apache的cxf框架,所以就采用了cxf来实现webservice服务端,本身实现并没技术难点,但是项目为
webservice-自定义注解处理参数加解密问题
前一段项目中用到了webservice,正好自己之前也了解过一点apache的cxf框架,所以就采用了cxf来实现webservice服务端,本身实现并没技术难点,但是项目为了保证安全性,采用了传输加密的过程,所以大部分请求参数需要加密,返回参数也需要加密,大致流程是:
请求参数对称加密+对称秘钥非对称加密,
返回参数堆成加密+对称秘钥非对称加密
参数加密本身并不复杂,但是有些服务并不需要加密,有些则需要,加密工具类并不通用
string,datahandler等不能重用,虽然本质都是对字节数据加密,但是要写许多方法,还要方法参数,检查需要加解密处理的参数,然后寻找对应的类型处理方法调用.
逻辑很清晰,但是过程实现很恶心,最终这样实现了一版,但是并不合我的意.
如果能在拦截器中获取到参数列表,然后寻找对应的解码器解码,这样就比较简单了.但是难点是,如果标记参数,并指定被标记参数的解码器尼?
我想到了注解,注解就可以标记,参数,然后通过反射获取到注解,解析出内容.
本来想标记到参数上,但是一个个标记太麻烦,而且获取也不太方便,索性就放在方法上,用数组来接收.
问题解决.
代码实现
自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** * @author webservice请求参数自定义注解 * */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestHanleAnnotation {
Class[] handler() default {};
int[] index() default {};
}
参数解码器接口
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @author taoyuan *参数处理器 * @param <T> */ public abstract class ParamHandler<T> { //解码器实例缓存 public static final Map<Class,ParamHandler> hanlers=new ConcurrentHashMap<>(); //处理方法 abstract T handle(T t); }
解码器实现,这里并没有真正解码,只是在参数后面加了123
public class StringHandler extends ParamHandler<String> { @Override public String handle(String t) { return t+"123"; } }
服务方法注解使用
//表示第一个参数需要StringHandler处理
@RequestHanleAnnotation(index=0,handler=StringHandler.class)
public String test(String test, String test2) throws Exception {
System.out.println(test);
System.out.println(test2);
return "cesshi";
}
拦截器实现
import java.io.File; import java.lang.reflect.Method; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.MessageContentsList; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.log4j.Logger; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; /** * @author 都市桃源 */ public class EcrInInterceptor extends AbstractPhaseInterceptor<SoapMessage>{ private Logger log = Logger.getLogger(ContractLogicImpl.class); public EcrInInterceptor(){ // 在调用方法之前调用拦截器 super(Phase.PRE_INVOKE); } @Override public void handleMessage(SoapMessage msg) throws Fault { /*获取请求ip,拦截器中可以做下统一日志处理 HttpServletRequest httprequest = (HttpServletRequest)msg.get(AbstractHTTPDestination.HTTP_REQUEST); * */ //获取正在执行的方法 Method method = MsgUtil.getSoapMethod(msg); //解析注解,并处理参数 MessageContentsList contentsList = MessageContentsList.getContentsList(msg); MsgUtil.handle(method,contentsList); } @Override public void handleFault(SoapMessage message) { super.handleFault(message); }
注解解析工具类实现
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.MessageContentsList;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.invoker.MethodDispatcher;
import org.apache.cxf.service.model.BindingOperationInfo;
/** * @author ll * 获取方法名称 * */
public class MsgUtil {
/**根据消息获取调用方法 * @param msg * @return */
public static Method getSoapMethod(SoapMessage msg){
Exchange exchange = msg.getExchange();
BindingOperationInfo bop = exchange.get(BindingOperationInfo.class);
MethodDispatcher md = (MethodDispatcher) exchange.get(Service.class)
.get(MethodDispatcher.class.getName());
Method method = md.getMethod(bop);
return method;
}
public static void handle(Method method, MessageContentsList contentsList) {
if(method==null)return;
RequestHanleAnnotation reqAnno= method.getAnnotation(RequestHanleAnnotation.class);
int[] indexs = reqAnno.index();
if(indexs==null||indexs.length==0)return;
Class[] handlers = reqAnno.handler();
try {
//处理器实例
ParamHandler handler=null;
for(int i=0,len=indexs.length;i<len;i++){
//获取需要处理的参数
Object obj = contentsList.get(indexs[i]);
//从缓存中获取处理器实例
handler=ParamHandler.hanlers.get(handlers[i]);
if(handler==null){
//创建处理器实例
handler=(ParamHandler) handlers[i].newInstance();
//缓存处理器实例
ParamHandler.hanlers.put(handlers[i], handler);
}
contentsList.set(indexs[i], handler.handle(obj));
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
返回参数同样也可以注解实现,这里就不在赘述了,实现也比较简单.
**需要注意的是,拦截器拦截顺序不一样 拦截器统一继承 AbstractPhaseInterceptor类, 请求拦截 :super(Phase.PRE_INVOKE); 返回拦截: super(Phase.PRE_STREAM);**