发表于: 2018-03-07 23:05:27

1 526


今天完成的事情:


今天学习了拦截器、过滤器和监听器的一些知识,并实现了拦截器、过滤器的程序的Demo,监听器暂时还没有实现。


1、拦截器:

SpringMVC中实现Interceptor拦截请求是通过拦截器接口(HandlerInterceptor)来实现的。HandlerInterceptor有三个回调方法,preHandle在controller处理之前执行,postHandle在渲染之前执行,afterCompletion在渲染完毕之后执行。如果只需要实现三个回调方法中的某一个,Spring提供了HandlerInterceptorAdapter(拦截器适配器),允许我们只使用需要的回调方法。


之前做任务时,应用拦截器方法记录用户的登陆状态。拦截器类的代码如下:

public class Interceptor implements HandlerInterceptor {

@Autowired
   private StudentService studentService;

   @Override
   public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response, Object handler) throws Exception {

boolean checkResult = studentService.checkCookie(request,response);

       if (checkResult == true) {
return true;
       }else {
response.sendRedirect("/Task1-3/loginPage");
           return false;
       }
}


   @Override
   public void postHandle(HttpServletRequest request,
                          HttpServletResponse response, Object handler,
                          ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub

   }


   @Override
   public void afterCompletion(HttpServletRequest request,
                               HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub

   }

}

代码中的postHandle方法和afterCompletion方法都没有执行任何语句,但是不可或缺,要实现HandlerInterceptor接口,必须实现这三个方法。如果注释掉下边的两个方法,程序会报错。

如果现实中不需要这三个方法全部实现,那可以用HandlerInterceptorAdapter适配器。我做的demo如下:

public class testHandlerInterceptorAdapter extends HandlerInterceptorAdapter {
//此处所以三个回调方法都是空实现,preHandle返回true。

   @Autowired
   private StudentService studentService;

   /**
    * preHandle方法是进行处理器拦截用的,顾名思义,该方法将在Controller处理之前进行调用,SpringMVC中的Interceptor拦截器是链式的,可以同时存在
    * 多个Interceptor,然后SpringMVC会根据声明的前后顺序一个接一个的执行,而且所有的Interceptor中的preHandle方法都会在
    * Controller方法调用之前调用。SpringMVC的这种Interceptor链式结构也是可以进行中断的,这种中断方式是令preHandle的返
    * 回值为false,当preHandle的返回值为false的时候整个请求就结束了。
    */
   @Override
   public boolean preHandle(HttpServletRequest request,
                            HttpServletResponse response, Object handler) throws Exception {

boolean checkResult = studentService.checkCookie(request,response);

       if (checkResult == true) {
return true;
       }else {
response.sendRedirect("/Task1-3/loginPage");
           return false;
       }
}
}

我只使用了preHandle方法,其他两个方法不需要定义。


HandlerInterceptorAdapter和HandlerInterceptor两种方法在SpringMVC.xml中的配置没有本质差别。


2、过滤器:

过滤器(Filter)是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp,Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:

    是否调用目标资源(即是否让用户访问web资源)。

   调用目标资源之前或者之后,让一段代码执行。

   web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

根据网上资料做的一个小demo:

一个用来在网页上过滤特定词汇的过滤器:

过滤器类:


public class WordsFilter implements Filter {

private List<String> banWords = new ArrayList<String>(); // 禁用词
   private List<String> auditWords = new ArrayList<String>(); // 审核词
   private List<String> replaceWords = new ArrayList<String>(); // 替换词


   // WordsFilter过滤器只要一装载,WordsFilter对象只要一创建出来,init方法就会执行,init方法一执行,就会往List集合里面装东西。
   /*
    * 首先要将敏感词库读到系统里面去,而且敏感词库只要读一遍就行了。
    * 我们可以在静态代码块里面做,但是我们还有一种方法,可以在init方法里面做,
    * 因为filter对象只会创建一次,init方法也只会执行一次。
    */

   @Override
   public void init(FilterConfig filterConfig) throws ServletException {
try {
String path = WordsFilter.class.getClassLoader().getResource("dirtyWords").getPath();
           File[] files = new File(path).listFiles();
           for (File file : files) {
if (!file.getName().endsWith(".txt")) {
continue;
               }

BufferedReader br = new BufferedReader(new FileReader(file));
               String line = null;
               while ((line=br.readLine()) != null) {
String[] s = line.split("\\|");
                   if (s.length != 2) {
continue;
                   }
if (s[1].trim().equals("1")) {
banWords.add(s[0].trim());
                   }
if (s[1].trim().equals("2")) {
auditWords.add(s[0].trim());
                   }
if (s[1].trim().equals("3")) {
replaceWords.add(s[0].trim());
                   }
}
}
System.out.println("脏话过滤器启动。。。。。。。。。。。"); // 作断点调试用
           System.out.println("banWord="+banWords);// 列出所有禁用词
           System.out.println("replaceWords"+replaceWords);//列出所有替换词
       } catch (Exception e) {
throw new RuntimeException(e);
       }
}

@Override
   public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
       HttpServletResponse response = (HttpServletResponse) resp;

       // 检查提交数据是否包含禁用词
       /*
        * 此刻是不知道客户机要提交过来的数据的,也即不知道客户机会以什么名称提交数据过来,
        * 所以应得到客户机提交的所有数据,然后挨个检查,怎么得到客户机提交的所有数据呢?
        * 可得到客户机提交的所有数据的名称,然后挨个取出来检查即可。
        */
       Enumeration<String> e = request.getParameterNames();
       while (e.hasMoreElements()) {
String name = (String) e.nextElement();
           String data = request.getParameter(name);
           for (String regex : banWords) {
Pattern pattern = Pattern.compile(regex); // 编译regex这个正则表达式,得到代表此正则表达式的对象
               Matcher m = pattern.matcher(data); // 看data数据里面有没有和该正则表达式相匹配的内容
               if (m.find()) { // 匹配器的find方法若返回true,则客户机提交的数据里面有和正则表达式相匹配的内容
                   request.setAttribute("message", "文章中包含非法词汇,请检查后再提交!!!");
                   request.getRequestDispatcher("/message.jsp").forward(request, response);
                   return;
               }
}
}

chain.doFilter(request, response);
   }

@Override
   public void destroy() {

System.out.println("filter被destroy");
   }

}

在web.xml中注册这个过滤器:

<!--脏话过滤器-->
<filter>
 <filter-name>WordsFilter</filter-name>
 <filter-class>com.byou.util.WordsFilter</filter-class>
</filter>
<filter-mapping>
 <filter-name>WordsFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>


标记禁用词语,将词语写到resources文件夹下的一个txt文件中,在词语后写一个|标记和一个数字,表示禁用类型,1表示禁止,2表示审查,3表示替换。这里这标记了禁止。


然后当网页上传一个包含禁用词汇时,操作将不会得到执行,而是发生一个网页的跳转,提示输入禁用词,需要重新输入。

但是这里遇到一个问题,就是当输入禁用词的时候,网页跳转有问题,无法跳转到需要的页面。至少说明过滤器的功能达到了。明天针对这个再改改。



明天计划的事情:

继续学习监听器。


遇到的问题:

过滤器过滤到非法字段时,跳转页面失败。报错信息是无法找到网页。暂时没有解决。


收获:

学习自己写拦截器和过滤器,感觉很好。





返回列表 返回列表
评论

    分享到