zoukankan      html  css  js  c++  java
  • 设计模式

    概念

    将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

    常见例子

    Servlet Filter、Spring Interceptor均使用此设计模式,
    最常见的是javax.servlet.Filter,Servlet Filter 是 Java Servlet 规范中定义的组件,翻译成中文就是过滤器,它可以实现对 HTTP 请求的过滤功能,比如鉴权、限流、记录日志、验证参数等。
    假如要实现一个Filter,功能是针对所有的rest接口进行签名验证,签名正确的执行接口逻辑,错误的返回错误信息。我们只需要实现Filter接口即可。

    @Component
    public class RestSecurityFilter implements Filter {
    	private static final Logger logger = LoggerFactory.getLogger(RestSecurityFilter.class);
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    		// TODO Auto-generated method stub
    
    	}
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    			throws IOException, ServletException {
    
    		if (request instanceof HttpServletRequest) {
    			// 校验安全性
    			HttpServletRequest httpReq = (HttpServletRequest) request;
    			RequestMatcher matcher = new AntPathRequestMatcher("/rest/**");
    			if(matcher.matches(httpReq)) {
    				String sign = httpReq.getHeader("sign");
    				// 具体签名算法略...
    				boolean passed = validate(httpReq);
    				// 校验不通过,返回错误信息,不再执行下一职责
    				if (!passed) {
    					HttpServletResponse rp = (HttpServletResponse) response;
    					rp.setStatus(HttpStatus.SC_BAD_REQUEST);
    					rp.addHeader("restful validate error",
    							" 400 , Method Not Allowed,please check restful called paramters ! ");
    					rp.getWriter()
    							.write("Method Not Allowed,please check restful called paramters !");
    					return;
    				}
    			}
    		}
    		// 放行,执行下一Filter
    		chain.doFilter(request, response);
    	}
    
    	@Override
    	public void destroy() {
    		// TODO Auto-generated method stub
    
    	}
    
    }
    
    

    web.xml中配置

      	<filter>
    	    <filter-name>restSecurityFilter</filter-name>
    	    <filter-class>com.xxx.filter.restSecurityFilter</filter-class>
    	</filter>
    	<filter-mapping>
    	    <filter-name>restSecurityFilter</filter-name>
    	    <url-pattern>/rest/*</url-pattern>
    	</filter-mapping>
    

    需求场景

    业务上需要校验企业信息,依次按照企业名称、社会统一信用代码、注册号等信息进行匹配,其中每种匹配规则有自己的业务逻辑,匹配成功的,不进行下一规则匹配。全部匹配完成之后,如未匹配成功则记为匹配失败。

    使用责任链的好处是各业务处理指责单一,易扩展。如后期要加入新的匹配规则,则只需要新增一个handler业务处理类即可,其它均不需要修改。

    代码示例

    public class CalibrateHandlerChain {
        private CalibrateHandler head = null;
        private CalibrateHandler tail = null;
    
        public void addHandler(CalibrateHandler handler) {
            handler.setNextHandler(null);
            if (head == null) {
                head = handler;
                tail = handler;
                return;
            }
            tail.setNextHandler(handler);
            tail = handler;
        }
    
        public void process(List<Company> companyList) {
            if (head != null) {
                head.process(companyList);
            }
        }
    
    }
    
    @Component
    public abstract class CalibrateHandler {
    
        /**
         * next handler,此处使用链表方式实现,也可使用数组
         */
        protected CalibrateHandler nextHandler = null;
    
        public void setNextHandler(CalibrateHandler calibrateHandler) {
            this.nextHandler = calibrateHandler;
        }
    
        /**
         * loop execution the method of calibrateHandlerChain
         */
        public final void process(List<Company> companyList) {
    		// 执行当前的handle,执行完成后,进入下一handler
            doHandle(companyList);
            if (nextHandler != null) {
                nextHandler.process(companyList);
            }
        }
    
        /**
         * abstract method subclass to impl
         *
         * @param companyList
         */
        protected abstract void doHandle(List<Company> companyList);
    
    }
    
    
    @Component
    @Order(1)
    public class XXXHandler extends CalibrateHandler {
    
        @Override
        protected void doHandle(List<Company> companyList) {
            // 企业名称匹配
    
        }
    }
    
    @Component
    @Order(2)
    public class YYYHandler extends CalibrateHandler {
    
        @Override
        protected void doHandle(List<Company> companyList) {
            // 社会统一信用代码匹配
    
        }
    }
    
    ...
    

    调用方

    @Service
    public class xxxService {
        @Autowired
        private List<CalibrateHandler> calibrateHandlerList;
    	
    	public void calibrateCompany(List<Company> companyList) {
    		CalibrateHandlerChain chain = new CalibrateHandlerChain();
    		// calibrateHandlerList中元素按照@Order排序,依次加入责任链
    		calibrateHandlerList.forEach(handler -> chain.addHandler(handler));
    		chain.process(companyList);
    	}
    
    }
    
    
  • 相关阅读:
    C语言中可变函数参数变量的实现
    Oracle电话面试
    JS和C#方法相互调用
    asp.net 页面从初始化到卸载事件顺序
    解决.NET CF 3.5 Bitmap(Stream)未处理异常问题
    sql2008新增时间类数据类型学习
    c#和Javascript操作同一json对象
    被研究生了
    分形
    跑钱
  • 原文地址:https://www.cnblogs.com/iiot/p/15305784.html
Copyright © 2011-2022 走看看