- 在做微服务项目中,网关服务的逻辑需要做'黑名单'、'验签'的限制,run()原本的代码是这样的。
@Override public Object run() throws ZuulException { // 1、获取请求对象 RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); HttpServletResponse response = ctx.getResponse(); response.setContentType("UTF-8"); String ipAddres = getIpAddr(request); // 2、黑名单限制 从数据库获取黑名单IP MeiteBlacklist blacklist = blacklistMapper.findBlacklist(ipAddres); if (blacklist != null) { resultError(ctx, "ip: "+ipAddres+", 没有权限!"); } // 3、验证签名 客户端请求是参数依然是明文,防止数据篡改。 但是url加个sign=密码。密码:客户端请求是所有参数md5加密。用参数sign加个参数MD5加密,服务端再验证下 Map<String, String> stringStringMap = SignUtil.toVerifyMap(request.getParameterMap(), false); if(!SignUtil.verify(stringStringMap)){ resultError(ctx, "参数被修改,验签失败!"); } // 4、xss、sql注入 return null; }
// 这个方法里有很多行为:黑名单限制、验签、xss、sql注入....等行为。如果接着一行一行写,维护性不是很强。
这里使用建造者模式进行重构。
- 建造者模式
- 定义一个创建接口
public interface GatewayBuild { /** * 黑名单拦截 */ Boolean blackBlock(RequestContext ctx, String ipAddres, HttpServletResponse response); /** * 参数验证 */ Boolean toVerifyMap(RequestContext ctx, String ipAddres, HttpServletRequest request); // xss //sql注入..... }
- 参数创建者
@Slf4j @Component public class VerificationBuild implements GatewayBuild { @Override public Boolean blackBlock(RequestContext ctx, String ipAddres, HttpServletResponse response) { log.info("黑名单逻辑..........................."); return true; } @Override public Boolean toVerifyMap(RequestContext ctx, String ipAddres, HttpServletRequest request) { log.info("验签逻辑..........................."); return false; } }
- 定义建造者组装类
@Component public class GatewayDirector { @Resource(name = "verificationBuild") private GatewayBuild gatewayBuild; public void direcot(RequestContext ctx, String ipAddres, HttpServletResponse response, HttpServletRequest request) { // 调用黑名单拦截方法 Boolean blackBlock = gatewayBuild.blackBlock(ctx, ipAddres, response); if (!blackBlock) { return; } // 调用参数验证方法 Boolean verifyMap = gatewayBuild.toVerifyMap(ctx, ipAddres, request); if (!verifyMap) { return; } // css、sql注入 } }
- 最终实现
run()最终实现代码@Override public Object run() throws ZuulException { // 1、获取请求对象 RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); HttpServletResponse response = ctx.getResponse(); response.setContentType("UTF-8"); String ipAddres = getIpAddr(request); gatewayDirector.direcot(ctx, ipAddres, response, request); return null; }
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的