通过 Spring AOP 注解实现自动代理
jopen
10年前
最近在做一个数据对接项目,通过Hessian与其他企业对接数据。但是公司电脑不能上网只能通过DL上网。如果每个方法都写代理的代码太繁琐,而 且项目发布到服务器上的时候服务器是可以上网的。即便通过配置文件配置各个类是否使用代理,但是当发布的时候修改配置文件的内容也会比较多。所以就想到了 通过注解+AOP的方式实现自动调用代理。
HTTP代理接口如下,其中的startProxy()为开始使用代理,endProxy()为结束使用代理,在需要用到的时候开启,不用的时候关闭,这样避免其他不需要使用代理的接口出现问题。
package com.tiamaes.gjds.proxy; /** * <p>类描述: Http代理接口</p> * <p>创建人:王成委 </p> * <p>创建时间:2015年1月16日 上午9:00:53 </p> * <p>版权说明: © 2015 Tiamaes </p> */ public interface HttpProxy { public void startProxy(); public void endProxy(); public String getUsername(); public void setUsername(String username); public String getPassword(); public void setPassword(String password); public String getHost(); public void setHost(String host); public int getPort(); public void setPort(int port); }
实现类如下
package com.tiamaes.gjds.proxy; import java.net.Authenticator; import java.net.PasswordAuthentication; /** * <p>类描述: Http代理</p> * <p>创建人:王成委 </p> * <p>创建时间:2015年1月15日 下午5:09:16 </p> * <p>版权说明: © 2015 Tiamaes </p> */ public class ProxyAuthentication extends Authenticator implements HttpProxy{ private String username; private String password; private String host; private int port; public ProxyAuthentication(){ } public ProxyAuthentication(String host,int port){ this.host = host; this.port = port; } public ProxyAuthentication(String host,int port,String username,String password){ this.host = host; this.port = port; this.username = username; this.password = password; } public PasswordAuthentication getPasswordAuthentication(){ return new PasswordAuthentication(username,password.toCharArray()); } /** * 开始使用代理 * @author 王成委 */ public void startProxy(){ System.setProperty("http.proxySet", "true"); System.setProperty("http.proxyHost", host); System.setProperty("http.proxyPort", String.valueOf(port)); if(username != null && !"".equals(username)) Authenticator.setDefault(this); } /** * 停止使用代理 * @author 王成委 */ public void endProxy(){ //System.se System.setProperty("http.proxySet", "false"); System.setProperty("http.proxyHost", ""); System.setProperty("http.proxyPort", ""); Authenticator.setDefault(null); } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } }
注解的代码如下
package com.tiamaes.gjds.dxp.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * <p>类描述: 使用代理设置 </p> * <pre>:eg * @UseProxy * public Object getByHttp(){ * ...... * } * </pre> * <p>创建人:王成委 </p> * <p>创建时间:2015年2月9日 下午4:41:27 </p> * <p>版权说明: © 2015 Tiamaes </p> * @see com.tiamaes.gjds.dxp.aop.ProxyManager * */ @Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface UseProxy { }
AOP切面的代码如下,这个是核心代码,原理就是监控带有UseProxy注解的方法,在方法执行前调用startProxy启动代理在方法执行结束后调用endProxy结束代理。
package com.tiamaes.gjds.dxp.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import com.tiamaes.gjds.proxy.HttpProxy; /** * <p>类描述: 通过注解{@link com.tiamaes.gjds.dxp.annotation.UseProxy}配置方法使用Http代理 </p> * <p>创建人:王成委 </p> * <p>创建时间:2015年2月9日 下午4:42:06 </p> * <p>版权说明: © 2015 Tiamaes </p> * @see com.tiamaes.gjds.dxp.annotation.UseProxy */ @Aspect public class ProxyManager { private HttpProxy httpProxy; private boolean proxyEnabled = true; public void setHttpProxy(HttpProxy httpProxy) { this.httpProxy = httpProxy; } public void setProxyEnabled(boolean proxyEnabled) { this.proxyEnabled = proxyEnabled; } @Pointcut("@annotation(com.tiamaes.gjds.dxp.annotation.UseProxy)") public void proxyAspect() { } @Around("proxyAspect()") public Object doInvoke(ProceedingJoinPoint joinPoint) throws Throwable{ if(httpProxy == null || !proxyEnabled){ return joinPoint.proceed(); } this.httpProxy.startProxy(); Object result = joinPoint.proceed(); this.httpProxy.endProxy(); return result; } }
Spring配置如下
<bean id="httpProxy" class="com.tiamaes.gjds.proxy.ProxyAuthentication"> <property name="host" value="192.168.38.69"/> <property name="port" value="808" /> <property name="username" value="user001" /> <property name="password" value="123456" /> </bean> <bean id="proxyManager" class="com.tiamaes.gjds.dxp.aop.ProxyManager"> <property name="httpProxy" ref="httpProxy" /> </bean>
使用方法如下
@UseProxy @Override public List<DriverInfo> GetDriverInfos(List<QueryInfo> queryInfos, int page, int pageSize) throws HessianException{ List<DriverInfo> drivers = null; try { KeliDriverQueryApi api = this.createApiByUrlKey(KeliDriverQueryApi.API_URL, KeliDriverQueryApi.class); drivers = api.GetDriverInfos(queryInfos, page, pageSize); } catch (MalformedURLException e) { throw new ConnotGetHessianApiException("无法创建远程接口"); } return drivers; }
只需要在方法上面加一个注解就可以实现自动调用HTTP代理。在不需要HTTP代理的时候直接把Spring配置文件中关的内容删掉就可以了,其实直接删除ProxyManager的配置就可以了。
来源:王成委的博客