zoukankan      html  css  js  c++  java
  • JavaWeb过滤器

    1.JavaWeb三大组件都需要在web.xml中进行配置

    2.过滤器

      它会在一组资源(jsp、servlet、.css、.html等等)的前面执行!

    它可以让请求得到目标资源,也可以不让请求达到!

      *过滤器有拦截请求的能力!

    过滤器如何编写

    1.写一个类实现Filter接口

    2.在web.xml中进行配置

     Filter接口

    void init(FilterConfig)

      *创建之后马上执行;Filter会在服务器启动时就创建!

    void destory()

      *销毁之前执行!在服务器关闭的时候销毁

    void doFilter(ServletRequest ,  ServletResponse,  FilterChain)

      *每次过滤时都会执行

    Filter是单例的!

    web.xml中配置:

    <filter>
      <filter-name>xxx</filter-name>
      <filter-class>com.xjs.web.filter.AFilter</filter-class>
    </filter>
    
    <filter-mapping>
      <filter-name>xxx</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

    使用:

    写一个过滤器AFilter:

    package com.xjs.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class AFilter implements Filter{
    
        /**
         * 创建之后马上执行,用来做初始化!
         */
        @Override
        public void init(FilterConfig arg0) throws ServletException {
            System.out.println("过滤器出生");
        }
        
        /**
         * 每次过滤时都会执行
         */
        @Override
        public void doFilter(ServletRequest arg0, ServletResponse arg1,
                FilterChain arg2) throws IOException, ServletException {
            System.out.println("开始拦截");
        }
        
        /**
         * 销毁之前执行,用来做对非内存资源进行释放
         */
        @Override
        public void destroy() {
            System.out.println("过滤器销毁");
        }
    }

    然后在web.xml中配置Filter,指定过滤哪些路径(这里是AServlet)

      <filter>
          <filter-name>xx</filter-name>
          <filter-class>com.xjs.filter.AFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>xx</filter-name>
          <url-pattern>/AServlet</url-pattern>
      </filter-mapping>

    AServlet:

    package com.xjs;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class AServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            System.out.println("AServlet....");
        }
    }

    当请求AServlet时被过滤器拦截。


    FilterConfig--->与ServletConfig相似

      * 获取初始化参数:getInitParameter()

      * 获取过滤器名称:getFilterName()

      * 获取application:getServletContext()

    FilterChain

      * doFilter(ServletRequest,  ServletResponse):放行!

      放行,就相当于调用了目标Servlet的service()方法。


    多过滤器

    FilterChain#doFilter()方法:

      执行目标资源,或者执行下一个过滤器!

    过滤器的四种拦截方式

          <dispatcher>REQUEST</dispatcher>  默认的!
          <dispatcher>FORWARD</dispatcher>
          <dispatcher>INCLUDE</dispatcher>
          <dispatcher>ERROR</dispatcher>
      <error-page>
          <error-code>500</error-code>
          <location>500.jsp</location>
      </error-page>

    在<filter-mapping>中进行配置!

    多个过滤器的执行顺序

    <filter-mapping>的配置顺序决定了过滤器的执行顺序!

    创建的FIlter

    过滤器的应用场景

      过滤器的应用场景:

        *执行目标资源之前做预处理工作,例如设置编码,这种通常会放行,只是在目标资源执行之前做的一些准备工作;

          几乎所有的Servlet中都需要写request.setCharacterEndoing()可以把它放到一个Filter中

      

        *通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;

        *在目标资源执行之后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理;

          回程拦截!


     案例1:分ip统计网站次数

    ip count
    192.168.1.111 5
    192.168.1.112 62

      统计工作需要在所有资源之前都执行,那么就可以放到Filter中了。

      我们这个过滤器不打算做拦截操作!因为我们只是用来做统计的。

      用什么东西来装载统计的数据。Map<String, Integer>

      整个网站只需要一个Map即可!

      Map什么时候创建(使用ServletContextListener,在服务器启动时完成创建,并保存到ServletContext中),Map保存到哪里!(Map保存到ServletContext中!!!)

        > Map需要在Filter中用来保存数据

        > Map需要在页面使用,打印Map中的数据

     1).网站统计每个IP地址访问本网站的次数。

    使用的是注解(代替了在web.xml中的配置)

    AListener监听器:

    package com.xjs.web.listener;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.annotation.WebListener;
    
    @WebListener
    public class AListener implements ServletContextListener {
    
        /**
         * 在服务器启动时创建Map,保存到ServletContext
         */
        public void contextInitialized(ServletContextEvent sce) {
            //创建Map
            Map<String,Integer> map=new LinkedHashMap<String,Integer>();
            //得到ServletContext
            ServletContext application = sce.getServletContext();
            application.setAttribute("map", map);
        }
        
        public void contextDestroyed(ServletContextEvent arg0) {
            
        }
    }

    AFilter拦截器----负责统计访问次数

    package com.xjs.web.filter;
    
    import java.io.IOException;
    import java.util.Map;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    
    /**
     * 从application中获取Map
     * 从request中获取当前客户端的IP
     * 进行统计工作,结果保存到Map中
     * @author hp
     *
     */
    @WebFilter("/*")
    public class AFliter implements Filter {
        private FilterConfig config;
    
        public void destroy() {
            
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            /*
             * 1.得到application中的 map
             * 2.从request中获取当前客户端的ip地址
             * 3.查看map中是否存在这个IP对应的访问次数,如果存在,把次数+1再保存回去
             * 4.如果不存在这个Ip ,那么说明第一次访问本站,设置访问次数为1
             */
            ServletContext application = config.getServletContext();
            Map<String,Integer> map = (Map<String,Integer>)application.getAttribute("map");
            
            //获取客户端IP地址
            String ip = request.getRemoteAddr();
            //进行判断
            if(map.containsKey(ip)){//这个IP在map中存在
                Integer count = map.get(ip);
                map.put(ip, count+1);
            }else{//不存在
                map.put(ip, 1);
            }
            application.setAttribute("map", map);//把map在放回到application中
            chain.doFilter(request, response);
        }
        
        /**
         * 在服务器启动时调用,而且只执行一次
         */
        public void init(FilterConfig fConfig) throws ServletException {
            this.config=fConfig;
        }
    }

    show.jsp---显示本项目的访问次数

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <body>
        <h1 align="center">显示结果</h1>
        <table align="center" width="60%" border="1">
            <tr>
                <th>IP</th>
                <th>COUNT</th>
            </tr>
            <c:forEach items="${applicationScope.map }" var="entry">
                <tr>
                    <td>${entry.key }</td>
                    <td>${entry.value }</td>
                </tr>
            </c:forEach>
        </table>
    </body>

     结果:

    案例2:粗粒度权限控制(拦截是否登录、拦截用户名admin权限)

    1)什么是粗粒度和细粒度权限

      粗粒度权限管理,对资源类型的权限管理。资源类型比如:菜单、url链接、用户添加页面、用户信息、类方法、页面中按钮,等等。。。

      粗粒度权限管理比如:超级管理员可以访问用户添加页面、用户信息等全部页面。

      细粒度权限管理,对资源实例的权限管理。资源实例就资源类型的具体化,比如:用户id为001的修改链接,1110班的用户信息。

      细粒度权限管理就是数据级别的权限管理。比如:部门经理可以访问本部门的员工信息,用户只可以看到自己的菜单,大区经理只能查看本辖区的销售订单。。


    粗粒度和细粒度例子:
     系统有一个用户列表查询页面,对用户列表查询分权限,如果粗颗粒管理,张三和李四都有用户列表查询的权限,张三和李四都可以访问用户列表查询。
    进一步进行细颗粒管理,张三(行政部)和李四(开发部)只可以查询自己本部门的用户信息。张三只能查看行政部 的用户信息,李四只能查看开发部门的用户信息。细粒度权限管理就是数据级别的权限管理。


    分为管理员,普通用户,游客。

    管理员能访问的资源(jsp) 放到admin文件夹下。

    普通用户能访问的资源(jsp)放到users文件夹下。

    写两个Filter过滤器对资源的访问进行过滤。

    UserFilter.java:----用户和管理员都能访问

    package com.xjs.web.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    @WebFilter("/admin/*")
    public class AdminFilter implements Filter {
    
        public void destroy() {
            
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            
            /*
             * 1.得到session 2.判断session域中是否存在 admin,如果存在,放行
             * 3.判读session域中是否存在username,如果存在,放行,否则打回login.jsp
             */
            HttpServletRequest req = (HttpServletRequest) request;
            HttpSession session = req.getSession();
            String name = (String) session.getAttribute("admin");
            if (name != null) {//管理员
                chain.doFilter(request, response);
            } else {
                req.setAttribute("msg", "您可能是个啥,但肯定不是管理员!");
                req.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        }
        public void init(FilterConfig fConfig) throws ServletException {
            
        }
    
    }

    AdminFilter.java:---只有管理员才能访问

    package com.xjs.web.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    
    @WebFilter("/admin/*")
    public class AdminFilter implements Filter {
    
        public void destroy() {
            
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            
            /*
             * 1.得到session 2.判断session域中是否存在 admin,如果存在,放行
             * 3.判读session域中是否存在username,如果存在,放行,否则打回login.jsp
             */
            HttpServletRequest req = (HttpServletRequest) request;
            HttpSession session = req.getSession();
            String name = (String) session.getAttribute("admin");
            if (name != null) {//管理员
                chain.doFilter(request, response);
            } else {
                req.setAttribute("msg", "您可能是个啥,但肯定不是管理员!");
                req.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        }
        public void init(FilterConfig fConfig) throws ServletException {
            
        }
    
    }

    LoginServlet:----用登录来区分身份

    package com.xjs;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public final class LoginServlet extends HttpServlet {
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            
            /*
             * 1.获取用户名
             * 2.判断用户名中是否包含itcast
             *     3.包含,就是管理员
             *     4.不包含,就是普通会员
             * 5.要把登录的信息保存到session中
             * 6.转发到index.jsp
             */
            String username = request.getParameter("username");
            if(username.contains("itcast")){
                request.getSession().setAttribute("admin", username);;
            }else{
                request.getSession().setAttribute("username", username);
            }
            request.getRequestDispatcher("/index.jsp").forward(request, response);    
        }
    }

    案例3:解决全站字符乱码(POST和GET中文编码问题)

    总在Servlet中写:Post----request.setCharacterEncoding("utf-8");
    
              Get-----String username=request.getParameter("username");
                    username=new String(username.getBytes("ISO-8859-1"), "utf-8");

     在Tomcat8之前,使用get方式得到参数会有乱码,在Tomcat8中默认编码为UTF-8。所以在Tomcat8中Get获取参数,不用考虑编码问题。

    1) 编写一个过滤器EncodingFilter.java:---完成对POST请求和GET请求编码问题

    package com.xjs.web.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    
    @WebFilter("/*")
    public class EncodingFilter implements Filter {
    
        public void destroy() {
        }
        
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            //处理post请求编码问题
            request.setCharacterEncoding("utf-8");
            
            HttpServletRequest req=(HttpServletRequest) request;
            /*
             * 处理Get请求的编码问题
             */
            /*
             * 掉包request
             * 1.写一个request的装饰类
             * 2.在放行时,使用我们自己的request
             */
            if(req.getMethod().equals("GET")){
                //向这个类传递一个HttpServletRequest,完成getParameter()方法的重写,然后回返回一个重写后的Request对象(具有得到参数为utf-8的能力)
                EncodingRequest er=new EncodingRequest(req);
                chain.doFilter(er, response);//--这个er(request)是装饰之后的request,它的getParameter();得到的参数是utf-8编码
            }else if(req.getMethod().equals("POST")){
                chain.doFilter(request, response);
            }
            
        }
    
        public void init(FilterConfig fConfig) throws ServletException {
        }
    
    }

     这里面在处理GET请求时,涉及到Filter中的参数为ServletRequest需要强制类型转换成HttpServletRequest,然后就是通过一个EncodingRequest类完成对request对象的getParameter()方法的重写。然后把对getParameter()装饰过的request对象放行------->传递到相应的Servlet的doGet方法中。

    2)EncodingRequest.java: 

      (1)原本EncodingRequest实现HttpServletRequest接口,重写String  getParameter(String name)方法

    EncodingRequest implements HttpServletRequest 重写getParameter()方法
    private
    HttpServletRequest request; public EncodingRequest(HttpServletRequest request) { this.request = request; } public String getParameter(String name) { String value = request.getParameter(name); // 处理编码问题 try { value = new String(value.getBytes("iso-8859-1"), "utf-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(); } return value; }

       (2)Java提供了HttpServletRequestWrapper类,只需EncodingRequest继承HttpServletRequestWrapper该类,重写getParameter()方法即可。

    Wrapper:包装器的意思

    package com.xjs.web.filter;
    
    import java.io.UnsupportedEncodingException;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    
    /**
     * 装饰request
     * 
     * @author hp
     *
     */
    public class EncodingRequest extends HttpServletRequestWrapper {
        private HttpServletRequest req;
    
        // java提供了这个类,只需实现这个构造器
        public EncodingRequest(HttpServletRequest request) {
            super(request);
            this.req = request;
        }
    
        public String getParameter(String name) {
            String value = req.getParameter(name);
            // 处理编码问题
            try {
                value = new String(value.getBytes("iso-8859-1"), "utf-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException();
            }
            return value;
        }
    }

    案例4:页面静态化之准备工作()

     什么是页面静态化!

    首次访问去数据库获取数据,然后把数据保存到一个html页面中

    二次访问,就不再去数据库获取了,而是直接显示html

     1.给出一个过滤器,把servlet请求的资源所做输出保存到html中,重定向到html页面。

    二次访问时,这个html页面已经存在,那么直接重定向,不用再去访问servlet!

    //////////////////////////////////////////////////////////////////

    原来在jsp上显示,HttpServletResponse的getWriter()方法得到的PrintWriter对象是与jsp绑定在一起,把响应的内容输出到了jsp页面上了。PrintWriter(String  fileName, String  can)构造方法可以创建指定文件的名称(路径),和字符集。

    所以我们调包response的getWriter()方法:----返回一个jsp页面使用它向html页面输出内容的PrintWriter对象

    package com.xjs.web.filter;
    
    import java.io.FileNotFoundException;
    import java.io.PrintWriter;
    import java.io.UnsupportedEncodingException;
    
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    /**
     * 是你还有你,一切拜托你
     * @author hp
     *
     */
    public class StaticResponse extends HttpServletResponseWrapper {
        private HttpServletResponse response;
        private PrintWriter pw;
    
        /**
         * String path:html文件路径!
         * @param response
         * @param path
         * @throws UnsupportedEncodingException 
         * @throws FileNotFoundException 
         */
        public StaticResponse(HttpServletResponse response,String path) throws FileNotFoundException, UnsupportedEncodingException {
            super(response);//一切拜托你
            this.response=response;
            
            //创建一个与html文件路径绑定在一起的流对象
            pw=new PrintWriter(path,"utf-8");
        }
        
        //自己需要增强的部分
        public PrintWriter getWriter(){
            //返回一个与html绑定在一起的printWriter对象
            //jsp会使用它进行输出,这样数据都输出到了html文件中!
            return pw;
        }
    }

     这个过滤器判断是否是第一次访问(也就是有无html页面)

     在这个里面生成html文件也就是在执行chain.doFilter(req,sr)放行时,传递的是装饰过的Response对象,会执行BookServlet,然后转发到show.jsp(并没有显示),使用装饰后的Response对象中的getWriter()方法得到PrintWriter对象,向html上输出内容,生成了html页面。

    然后再重定向到html页面即可!

    package com.xjs.web.filter;
    
    import java.io.File;
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    @WebFilter(servletNames = { "BookServlet" })
    public class StaticFilter implements Filter {
    
        public void destroy() {
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req=(HttpServletRequest) request;
            HttpServletResponse res=(HttpServletResponse) response;
            /*
             * 1.第一次访问时,查找请求对应的html页面是否存在,如果存在重定向到html
             * 2.如果不存在,放行!把servlet访问数据库后,输出给客户端的数据保存到一个html文件中
             *     再重定向到html
             */
            /*
             * 一、获取category参数!
             * null--->null.html
             * 1--->1.html
             * 2--->2.html
             * 3---->3.html
             * htmls目录下
             */
            String category = req.getParameter("category");
            String htmlPage=category+".html";//得到对应文件的名称
            String htmlPath=req.getServletContext().getRealPath("/htmls");//得到文件存放目录
            File destFile=new File(htmlPath,htmlPage);
            
            if(destFile.exists()){//如果文件存在
                //重定向到这个文件
                res.sendRedirect(req.getContextPath()+"/htmls/"+htmlPage);
                return;
            }
            
            /*
             * 二、如果html文件不存在,我们要生成html文件
             * 1.放行,show.jsp会做出很多的输出,我们要让它不再输出客户端,而是输出到我们指定的一个html文件中
             * 完成:
             *     调包response,让它的getWriter()与一个html文件绑定,那么show.jsp的输出就到了html文件中
             * 
             */
            StaticResponse sr=new StaticResponse(res, destFile.getAbsolutePath());//文件的绝对路径。
            chain.doFilter(req, sr);//放行,即生成了html文件
            //这时页面已经存在,重定向到html文件
            res.sendRedirect(req.getContextPath()+"/htmls/"+htmlPage);
        }
    
        public void init(FilterConfig fConfig) throws ServletException {
        }
    }

    BookServlet.java:

    package com.xjs.web.servlet;
    
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.xjs.web.dao.BookDao;
    
    import cn.itcast.servlet.BaseServlet;
    
    public class BookServlet extends BaseServlet {
    
        private BookDao bookDao=new BookDao();
        
        public String findAll(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            request.setAttribute("bookList", bookDao.findAll());
            return "/show.jsp";
        }
        
        public String findByCategory(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String value = request.getParameter("category");
            int category = Integer.parseInt(value);
            request.setAttribute("bookList", bookDao.findByCategory(category));
            return "/show.jsp";
        }
    }

     link.jsp:显示链接

      <body>
        <h1>链接页面</h1>
        <a href='<c:url value="/BookServlet?method=findAll"></c:url>'>查看所有</a><br>
        <a href='<c:url value="/BookServlet?method=findByCategory&category=1"></c:url>'>查看SE</a><br>
        <a href='<c:url value="/BookServlet?method=findByCategory&category=2"></c:url>'>查看EE</a><br>
        <a href='<c:url value="/BookServlet?method=findByCategory&category=3"></c:url>'>查看Framework</a><br>
      </body>

     show.jsp:负责向html页面响应内容

    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <!-- 模拟html的响应头,告诉服务器html使用的编码 -->
    相当于向html页面加的响应头
    
    
    
    <body>
        <h1 align="center">图书列表</h1>
        <table border="1" align="center">
            <tr>
                <th>书名</th>
                <th>单价</th>
                <th>分类</th>
            </tr>
            <c:forEach items="${bookList }" var="book">
                <tr>
                    <td>${book.bname }</td>
                    <td>${book.price }</td>
                    <td>${book.category }</td>
                </tr>
            </c:forEach>
        </table>
    </body>

     

  • 相关阅读:
    VB程序逆向反汇编常见的函数(修改版)
    [反汇编练习] 160个CrackMe之009
    [反汇编练习] 160个CrackMe之008
    [反汇编练习] 160个CrackMe之007
    [反汇编练习] 160个CrackMe之006
    Delphi反汇编内部字符串处理函数/过程不完全列表
    [反汇编练习] 160个CrackMe之005
    [反汇编练习] 160个CrackMe之004
    新建Django配置
    mysql 常用命令大全
  • 原文地址:https://www.cnblogs.com/xjs1874704478/p/10961018.html
Copyright © 2011-2022 走看看