webservice-自定义注解处理参数加解密问题
webservice-自定义注解处理参数加解密问题前一段项目中用到了webservice,正好自己之前也了解过一点apache的cxf框架,所以就采用了cxf来实现webservice服务端,本身实现并没技术难点,但是项目为了保证安全性,采用了传输加密的过程,所以大部分请求参数需要加密,返回参数也需要加密,大致流程是: 请求参数对称加密+对称秘钥非对称加密, 参数加密本身并不复杂,但是有些服务并不需要加密,有些则需要,加密工具类并不通用 如果能在拦截器中获取到参数列表,然后寻找对应的解码器解码,这样就比较简单了.但是难点是,如果标记参数,并指定被标记参数的解码器尼? 代码实现自定义注解: 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);** (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |