为了解耦的任务校验,将校验对象连成一个链,沿着这个链进行访问,直到有一个对象处理位置;
1.按照一定的顺序执行判断;
2.避免校验对象之间耦合关系;
3.不用担心没有代码没有执行到;
这段代码总共做了 三件事: 1.过滤器链创建;2.过滤链逐个过滤;3.释放过滤链资源;
private void invoke(ServletRequest request, ServletResponse response, State state) throws IOException, ServletException { //。。。。。。。。前面的代码省略 // Get the FilterChain Here ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); //创建过滤器校验链条 // Call the service() method for the allocated servlet instance try { // for includes/forwards if ((servlet != null) && (filterChain != null)) { filterChain.doFilter(request, response); //进行过滤器校验 } // Servlet Service Method is called by the FilterChain } catch (ClientAbortException e) { //。。。。。。。省略中间错误判断代码 } // Release the filter chain (if any) for this request try { if (filterChain != null) filterChain.release();//释放过滤器资源 } catch (Throwable e) { ExceptionUtils.handleThrowable(e); wrapper.getLogger().error(sm.getString("standardWrapper.releaseFilters", wrapper.getName()), e); // FIXME: Exception handling needs to be similar to what is in the StandardWrapperValue } //。。。。。。。。。后面的代码省略 }
从下面可以看出主要是一下操作:
1.初始化ApplicatFilterChain 过滤器校验链;
2.从上下文环境中,获取之前配置的过滤器数据;
3.将符合URL,serveletName的过滤器配置到ApplicationFilterChain中
public static ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) { // If there is no servlet to execute, return null if (servlet == null) return null; // Create and initialize a filter chain object 初始化链式对象 ApplicationFilterChain filterChain = null; if (request instanceof Request) { Request req = (Request) request; if (Globals.IS_SECURITY_ENABLED) { // Security: Do not recycle filterChain = new ApplicationFilterChain(); } else { filterChain = (ApplicationFilterChain) req.getFilterChain(); if (filterChain == null) { filterChain = new ApplicationFilterChain(); req.setFilterChain(filterChain); } } } else { // Request dispatcher in use filterChain = new ApplicationFilterChain(); } filterChain.setServlet(servlet); filterChain.setServletSupportsAsync(wrapper.isAsyncSupported()); // Acquire the filter mappings for this Context 获取过滤器配置的上下文 StandardContext context = (StandardContext) wrapper.getParent(); FilterMap filterMaps[] = context.findFilterMaps(); // If there are no filter mappings, we are done if ((filterMaps == null) || (filterMaps.length == 0)) return filterChain; // Acquire the information we will need to match filter mappings DispatcherType dispatcher = (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR); String requestPath = null; Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR); if (attribute != null){ requestPath = attribute.toString(); } String servletName = wrapper.getName(); // Add the relevant path-mapped filters to this filter chain 将符合需求的过滤器加入到过滤链中 for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersURL(filterMaps[i], requestPath)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } filterChain.addFilter(filterConfig); } // Add filters that match on servlet name second for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersServlet(filterMaps[i], servletName)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } filterChain.addFilter(filterConfig); } // Return the completed filter chain return filterChain; }
这个方法比较简单:1.数组扩容;2.增加新的过滤器;
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];//过滤器存储的实体类 private int pos = 0;//当前过滤位置 private int n = 0;//存储的过滤器的总数 public static final int INCREMENT = 10; void addFilter(ApplicationFilterConfig filterConfig) { // Prevent the same filter being added multiple times for(ApplicationFilterConfig filter:filters) if(filter==filterConfig) return; if (n == filters.length) { ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT]; System.arraycopy(filters, 0, newFilters, 0, n); filters = newFilters; } filters[n++] = filterConfig; }
处理过程:
1.获取pos位置的过滤器;
2.Filter执行,将当前过滤链对象,作为参数进行传递;
3.pos过滤器后移1位进行调用,直到pos大于总过滤器位置;
@Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; try { java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<Void>() { @Override public Void run() throws ServletException, IOException { internalDoFilter(req,res); return null; } } ); } catch( PrivilegedActionException pe) { Exception e = pe.getException(); if (e instanceof ServletException) throw (ServletException) e; else if (e instanceof IOException) throw (IOException) e; else if (e instanceof RuntimeException) throw (RuntimeException) e; else throw new ServletException(e.getMessage(), e); } } else { internalDoFilter(request,response); } } //实际处理过滤任务的方法 private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++];//pos默认是从0开始的,调用后+1 try { Filter filter = filterConfig.getFilter(); if (request.isAsyncSupported() && "false".equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res, this}; SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal); } else { filter.doFilter(request, response, this);//这里是最重要的一点,过滤器将过滤链对象作为一个参数向下传递,从而可以自动的进行链式校验 } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { e = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString("filterChain.filter"), e); } return; } //。。。。。。。。。。省略部分代码 }
/** * 参数校验锁链管理 * @param * @author lpf */ public interface CheckChain{ public abstract void doCheck(Param param) throws Exception; }
public interface Param<T extends Param> { public abstract <T> T get(); }
@Service public interface CheckFilter<T extends Param> { /** * 参数校验方法 * @param chain * @return */ public abstract void checkParam(Param<T> param, CheckChain chain) throws Exception; }
/** * 默认链式检查 */ public class DefaultCheckChain implements CheckChain { /** * */ private ParamCheckWapper[] wappers = new ParamCheckWapper[0]; private static final int INCREMENT = 10; private int n = 0; private int pos = 0; //进行链式检查 @Override public void doCheck(Param filed) throws Exception { if(pos < n){ ParamCheckWapper wapper = wappers[pos++]; CheckFilter paramCheck = wapper.getParamCheck(); Assert.notNull(paramCheck,"链式类不能为空"); paramCheck.checkParam(filed,this); } } /** * 增加要进行过滤处理的类 * @param checkWapper */ public void addCheck(ParamCheckWapper checkWapper){ for(ParamCheckWapper wapper : wappers){ if(wapper == checkWapper){return;} ; } if(n == wappers.length){ ParamCheckWapper[] newWappers = new ParamCheckWapper[n + INCREMENT]; System.arraycopy(wappers, 0, newWappers, 0, n); wappers = newWappers; } wappers[n++] = checkWapper; } }
/** * select参数校验 * @author lpf * @since 2019-11-08 */ public class SelectParamCheck implements CheckFilter<CheckParam> { /** * 参数校验 * @param param * @param chain */ @Override public void checkParam(Param<CheckParam> param, CheckChain chain) throws Exception{ CheckParam checkParam = param.get(); List<SelectField> selects = checkParam.getSelect(); List<String> columns = checkParam.getColumnList(); //对select参数进行校验 selects.forEach(select -> { String filed = select.getFiled().toLowerCase(); boolean flag = columns.contains(filed); if(!flag) throw new RuntimeException(select.getFiled()+"不存在,请刷新页面重新选择查询字段!!!"); }); }
@Service public class SearchConfigService { /**默认检查链*/ private static DefaultCheckChain checkChain ; /**过滤链路表配置*/ static{ checkChain = new DefaultCheckChain(); //参数检查器 ParamCheckWapper selectParamCheck = new ParamCheckWapper(new SelectParamCheck(),"SelectParamCheck"); ParamCheckWapper groupParamCheck = new ParamCheckWapper(new GroupbyParamCheck(), "groupParamCheck"); ParamCheckWapper conditionParamCheck = new ParamCheckWapper(new ConditionParamCheck(), "conditionParamCheck"); ParamCheckWapper orderbyParamCheck = new ParamCheckWapper(new OrderbyParamCheck(), "orderbyParamCheck"); //参数链表增加过滤类 checkChain.addCheck(selectParamCheck); checkChain.addCheck(groupParamCheck); checkChain.addCheck(conditionParamCheck); checkChain.addCheck(orderbyParamCheck); } /** * 参数校验 */ public void doCheck(Param param) throws Exception { checkChain.doCheck(param); }
以上,就是职责链路模式的简单使用,可以通过泛型进行代码剥离,后续涉及到链式校验的时候就可以通过限制参数进行多样使用。降低代码的耦合度;