• JavaWeb学习总结(十五)--过滤器的应用


      一、解决全站字符乱码(post和get中文编码问题)

    乱码问题:

    •  获取请求参数中的乱码问题;
    1. POST请求:request.setCharacterEncoding(“utf-8”);
    2. GET请求:new String(request.getParameter(“xxx”).getBytes(“iso-8859-1”), “utf-8”);
    • 响应的乱码问题:
    1. response.setContextType(“text/html;charset=utf-8”)

    使用Decorator模式包装request对象解决get和post请求方式下的中文乱码问题

      编写一个用于处理中文乱码的过滤器CharacterEncodingFilter,代码如下:

     1 package cn.zy.filter;
     2 
     3 import java.io.IOException;
     4 import javax.servlet.Filter;
     5 import javax.servlet.FilterChain;
     6 import javax.servlet.FilterConfig;
     7 import javax.servlet.ServletException;
     8 import javax.servlet.ServletRequest;
     9 import javax.servlet.ServletResponse;
    10 import javax.servlet.http.HttpServletRequest;
    11 import javax.servlet.http.HttpServletRequestWrapper;
    12 import javax.servlet.http.HttpServletResponse;
    13 
    14 public class CharacterEncodingFilter implements Filter {
    15     private FilterConfig filterConfig = null;
    16     //设置默认的字符编码
    17     private String defaultCharset = "UTF-8";
    18 
    19     public void doFilter(ServletRequest req, ServletResponse resp,
    20             FilterChain chain) throws IOException, ServletException {
    21         HttpServletRequest request = (HttpServletRequest)req;
    22         HttpServletResponse response = (HttpServletResponse) resp;
    23         //得到在web.xml中配置的字符编码
    24         String charset = filterConfig.getInitParameter("charset");
    25         if(charset==null){
    26             charset = defaultCharset;
    27         }
    28         request.setCharacterEncoding(charset);
    29         response.setCharacterEncoding(charset);
    30         response.setContentType("text/html;charset="+charset);
    31         
    32         //使用得到加强的request
    33         EncodingRequest requestWrapper = new EncodingRequest(request);
    34          chain.doFilter(requestWrapper, response);
    35     }
    36 
    37     public void init(FilterConfig filterConfig) throws ServletException {
    38         this.filterConfig = filterConfig;
    39 
    40     }
    41     
    42     public void destroy() {
    43     }
    44     
    45     /*
    46      * 写一个装饰类增强HttpServletRequest对象
    47      */
    48      class EncodingRequest extends HttpServletRequestWrapper {
    49         //定义一个变量记住被增强对象(request对象是需要被增强的对象)
    50         private HttpServletRequest request;
    51         //定义一个构造函数,接收被增强对象
    52         public EncodingRequest(HttpServletRequest request) {
    53             super(request);
    54             this.request = request;
    55         }
    56         /* 覆盖需要增强的getParameter方法
    57          * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
    58          */
    59         @Override
    60         public String getParameter(String name) {
    61             try{
    62                 //获取参数的值
    63                 String value= this.request.getParameter(name);
    64                 if(value==null){
    65                     return null;
    66                 }
    67                 //如果不是以get方式提交数据的,就直接返回获取到的值
    68                 if(!this.request.getMethod().equalsIgnoreCase("get")) {
    69                     return value;
    70                 }else{
    71                     //如果是以get方式提交数据的,就对获取到的值进行转码处理
    72                     value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
    73                     return value;
    74                 }
    75             }catch (Exception e) {
    76                 throw new RuntimeException(e);
    77             }
    78         }
    79     }
    80 }

    在web.xml文件中配置Filter

    <filter>
          <filter-name>CharacterEncodingFilter</filter-name>
          <filter-class>cn.zy.filter.CharacterEncodingFilter</filter-class>
          <init-param>
              <param-name>name</param-name>
              <param-value>UTF-8</param-value>
          </init-param>
      </filter>
      <filter-mapping>
          <filter-name>CharacterEncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

    编写一个测试的用的jsp提交表单

     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     3 <%
     4 String path = request.getContextPath();
     5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
     6 %>
     7 
     8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     9 <html>
    10   <head>
    11     <base href="<%=basePath%>">
    12     
    13     <title>My JSP 'index.jsp' starting page</title>
    14     <meta http-equiv="pragma" content="no-cache">
    15     <meta http-equiv="cache-control" content="no-cache">
    16     <meta http-equiv="expires" content="0">    
    17     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    18     <meta http-equiv="description" content="This is my page">
    19     <!--
    20     <link rel="stylesheet" type="text/css" href="styles.css">
    21     -->
    22   </head>
    23   
    24   <body>
    25     <form action="<c:url value='/Aservlet'/>" method="post">
    26     用户名: <input type="text" name="username">
    27   <input type="submit" value="提交"/>  
    28    </form>
    29    <a href="<c:url value='/Aservlet?username=张三'/>">点击这里</a><br/>
    30   </body>
    31 </html>

    编写一个Servlet用于处理请求

     1 package cn.zy.filter;
     2 
     3 import java.io.IOException;
     4 import java.io.PrintWriter;
     5 
     6 import javax.servlet.ServletException;
     7 import javax.servlet.http.HttpServlet;
     8 import javax.servlet.http.HttpServletRequest;
     9 import javax.servlet.http.HttpServletResponse;
    10 
    11 public class Aservlet extends HttpServlet {
    12 
    13     /**
    14      * The doGet method of the servlet. <br>
    15      *
    16      * This method is called when a form has its tag value method equals to get.
    17      * 
    18      * @param request the request send by the client to the server
    19      * @param response the response send by the server to the client
    20      * @throws ServletException if an error occurred
    21      * @throws IOException if an error occurred
    22      */
    23     public void doGet(HttpServletRequest request, HttpServletResponse response)
    24             throws ServletException, IOException {
    25         String username = request.getParameter("username");
    26          //获取请求方式
    27        String method = request.getMethod();
    28        response.getWriter().print("请求方式" +method+"参数:"+username);    
    29     }
    30 
    31     
    32     public void doPost(HttpServletRequest request, HttpServletResponse response)
    33             throws ServletException, IOException {
    34         doGet(request, response);
    35     }
    36 
    37 }

    二、统计每个访问次数

    写一个监听器,在服务启动时创建一个map,用于保存访问IP和次数

     1 package cn.zy.listener;
     2 
     3 import java.util.LinkedHashMap;
     4 import java.util.Map;
     6 import javax.servlet.ServletContext;
     7 import javax.servlet.ServletContextEvent;
     8 import javax.servlet.ServletContextListener;
     9 
    10 public class CreateMapListener implements ServletContextListener {
    11 
    12     public void contextInitialized(ServletContextEvent sce) {
    13         /*
    14          * 在服务器启动时创建map
    15          */
    16         Map<String,Integer> map = new LinkedHashMap<String,Integer>();
    17         //得到ServletContext
    18         ServletContext application = sce.getServletContext();
    19         //把Map保存到ServletContext中
    20         application.setAttribute("map", map);
    21     }
    22     
    23     public void contextDestroyed(ServletContextEvent sce) {
    24 
    25     }
    26 
    27 }

    创建一个Filter用于统计访问次数

    package cn.zy.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;
    
    /*
     * 获取某个IP访问本站的次数
     */
    public class AccessCountFilter implements Filter {
        private FilterConfig config;
    
        public void destroy() {
        }
    
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            //1. 得到appliction
            ServletContext app = config.getServletContext();
            //2.从application中获取map
            Map<String,Integer> map = (Map<String, Integer>) app.getAttribute("map");
            //3.获取客户端的地址
            String ip = request.getRemoteAddr();
            /*
             * 4.进行判断IP是否是第一次访问,如果不是则加1,如果是则设置为1
             */
            if(map.containsKey(ip)){
                int cnt = map.get(ip);
                map.put(ip, cnt+1);
            }else{
                map.put(ip, 1);
            }
            //5.把map重新放回到app中
            app.setAttribute("map", map);
            //6.放行
            chain.doFilter(request, response);
        }
    
        public void init(FilterConfig filterConfig) throws ServletException {
            this.config=filterConfig;
    
        }
    
    }

    web.xml中的配置:

    <filter>
          <filter-name>AccessCountFilter</filter-name>
          <filter-class>cn.zy.filter.AccessCountFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>AccessCountFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
      
      
     <!-- 配置Listener -->
     <listener>
        <listener-class>cn.zy.listener.CreateMapListener</listener-class>
      </listener>

    创建一个jsp用于显示

     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
     3 <%
     4 String path = request.getContextPath();
     5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
     6 %>
     7 
     8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     9 <html>
    10   <head>
    11     <base href="<%=basePath%>">
    12     
    13     <title>My JSP 'show.jsp' starting page</title>
    14     
    15     <meta http-equiv="pragma" content="no-cache">
    16     <meta http-equiv="cache-control" content="no-cache">
    17     <meta http-equiv="expires" content="0">    
    18     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    19     <meta http-equiv="description" content="This is my page">
    20     <!--
    21     <link rel="stylesheet" type="text/css" href="styles.css">
    22     -->
    23 
    24   </head>
    25   
    26   <body>
    27    <h1 align="center">显示结果</h1>
    28 <table align="center" width="60%" border="1">
    29     <tr>
    30         <th>IP</th>
    31         <th>次数</th>
    32     </tr>
    33 <c:forEach items="${applicationScope.map }" var="entry">
    34     <tr>
    35         <td>${entry.key }</td>
    36         <td>${entry.value }</td>
    37     </tr>
    38 </c:forEach>
    39 </table>
    40   </body>
    41 </html>

    结果如下图所示:

    三、粗粒度权限控制(控制页面的访问权限)

    目的:

    我们给出三个页面:index.jsp、user.jsp、admin.jsp。

    l  index.jsp:谁都可以访问,没有限制;

    l  user.jsp:只有登录用户才能访问;

    l  admin.jsp:只有管理员才能访问。

    创建一个登陆界面,用于提交表单

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'login.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        <h1>登录</h1>
        ${msg }
        <form action="<c:url value='/LoginServlet' />" method="post">
        用户名:<input type="text" name="username" /><br>
       密码:<input type="password" name="password" /> <br>
       <input type="submit" value="提交">
        </form>
      </body>
    </html>

    2.创建一个Servlet处理表单

    package cn.zy.web.servlet;
    
    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 LoginServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            response.setContentType("text/html;charset=utf-8");
            
            /*
             * 1.获取用户名
             * 2.如果含有admin则是管理员
             * 3.如果不包含则为普通用户
             */
            
            String username = request.getParameter("username");
            if(username.contains("admin")){
                request.getSession().setAttribute("admin", username);
            }else{
                request.getSession().setAttribute("username", username);
            }
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request,response);
        }
    
    }

    2.创建一个jsp,用于链接到不同的页面

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
      </head>
      
      <body>
       <h1>你就是个游客而已</h1>
    <a href="<c:url value='/index.jsp'/>">游客入口</a><br/>
    <a href="<c:url value='/users/u.jsp'/>">会员入口</a><br/>
    <a href="<c:url value='/admin/a.jsp'/>">管理员入口</a><br/>
      </body>
    </html>

    3.创建两个jsp,内容就是普通用户能访问的页面和管理员才能访问的页面

    4.做两个过滤器,用于权限控制

    AdminFilter

    package cn.zy.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.http.HttpServletRequest;
    
    public class AdminFilter implements Filter {
    
        public void destroy() {
    
        }
    
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            //得到Session
            HttpServletRequest req = (HttpServletRequest)request;
            String name = (String)req.getSession().getAttribute("admin");
            if(name != null){
                chain.doFilter(request, response);
            }else{
                req.setAttribute("msg", "您不是管理员!");
                req.getRequestDispatcher("/login.jsp").forward(request, response);
            }
        }
    
        public void init(FilterConfig arg0) throws ServletException {
        }
    }

    UserFilter

    package cn.zy.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.http.HttpServletRequest;
    
    public class UserFilter implements Filter {
        
        public void init(FilterConfig filterConfig) throws ServletException {
            
        }
        
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            
            HttpServletRequest req = (HttpServletRequest) request;
            String name = (String)req.getSession().getAttribute("admin");
            if(name != null) {
                chain.doFilter(request, response);
                return;
            } 
            
            name = (String)req.getSession().getAttribute("username");
            if(name != null){
                chain.doFilter(request, response);
            }else{
                req.setAttribute("msg", "您不是管理员也不是会员!");
                req.getRequestDispatcher("/login.jsp").forward(request, response);
            }
    
        }
    
        public void destroy() {
        }
    
    }

    web.xml中的配置

    <filter>
        <display-name>UserFilter</display-name>
        <filter-name>UserFilter</filter-name>
        <filter-class>cn.zy.filter.UserFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>UserFilter</filter-name>
        <url-pattern>/users/*</url-pattern>
      </filter-mapping>
      <filter>
        <display-name>AdminFilter</display-name>
        <filter-name>AdminFilter</filter-name>
        <filter-class>cn.zy.filter.AdminFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>AdminFilter</filter-name>
        <url-pattern>/admin/*</url-pattern>
      </filter-mapping>

    四、 response增强案例——缓存数据到内存

    对于页面中很少更新的数据,例如商品分类,为避免每次都要从数据库查询分类数据,因此可把分类数据缓存在内存或文件中,以此来减轻数据库压力,提高系统响应速度。

      编写缓存数据的过滤器,代码如下:

    package cn.zy.filter;
    
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpServletResponseWrapper;
    
    public class WebResourceCachedFilter implements Filter {
        /**
        * @Field: map
        *          缓存Web资源的Map容器
        */ 
        private Map<String,byte[]> map = new HashMap<String,byte[]>();
        
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp,
                FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) resp;
            response.setCharacterEncoding("utf-8"); 
            //1.得到用户请求的uri
            String uri = request.getRequestURI();
            //2.看缓存中有没有uri对应的数据
            byte b[] = map.get(uri);
            //3.如果缓存中有,直接拿缓存的数据打给浏览器,程序返回
            if(b!=null){
                //根据字节数组和指定的字符编码构建字符串
                String webResourceHtmlStr = new String(b,response.getCharacterEncoding());
                System.out.println(webResourceHtmlStr);
                response.getOutputStream().write(b);
                return;
            }
            //4.如果缓存没有,让目标资源执行,并捕获目标资源的输出
            BufferResponse myresponse = new BufferResponse(response);
            chain.doFilter(request, myresponse);
            //获取缓冲流中的内容的字节数组
            byte out[] = myresponse.getBuffer();
            //5.把资源的数据以用户请求的uri为关键字保存到缓存中
            map.put(uri, out);
            //6.把数据打给浏览器
            response.getOutputStream().write(out);
        }
    
        public void destroy() {
    
        }
    
        class BufferResponse extends HttpServletResponseWrapper{
            private ByteArrayOutputStream bout = new ByteArrayOutputStream();  //捕获输出的缓存
            private PrintWriter pw;
            private HttpServletResponse response;
            public BufferResponse(HttpServletResponse response) {
                super(response);
                this.response = response;
            }
            @Override
            public ServletOutputStream getOutputStream() throws IOException {
                return new MyServletOutputStream(bout);
            }
            @Override
            public PrintWriter getWriter() throws IOException {
                pw = new PrintWriter(new OutputStreamWriter(bout,this.response.getCharacterEncoding()));
                return pw;
            }
            
            public byte[] getBuffer(){
                try{
                    if(pw!=null){
                        pw.close();
                    }
                    return bout.toByteArray();
                }catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    
        class MyServletOutputStream extends ServletOutputStream{
            private ByteArrayOutputStream bout;
            public MyServletOutputStream(ByteArrayOutputStream bout){  //接收数据写到哪里
                this.bout = bout;
            }
            @Override
            public void write(int b) throws IOException {
                bout.write(b);
            }
        }
    }

    在web.xml中配置Web资源缓存过滤器

    <filter>
           <description>Web资源缓存过滤器</description>
          <filter-name>WebResourceCachedFilter</filter-name>
          <filter-class>cn.zy.filter.WebResourceCachedFilter</filter-class>
      </filter>
      
      <filter-mapping>
          <filter-name>WebResourceCachedFilter</filter-name>
          <!-- 映射需要缓存输出的JSP页面,这几个页面都只是单纯作为输入UI,不会有太多的变化,因此可以缓存输出 -->
          <url-pattern>/login.jsp</url-pattern>
          <url-pattern>/test.jsp</url-pattern>
          <url-pattern>/test2.jsp</url-pattern>
      </filter-mapping>
  • 相关阅读:
    JS使用 popstate 事件监听物理返回键
    JQ判断div是否隐藏
    SQL Server DATEDIFF() 函数
    取消a或input标签聚焦后出现虚线框
    C#定时任务
    C# 保留N位小数
    C#打印单据
    SQL语句创建函数
    SVN检出新项目
    解决jQuery的toggle()的自动触发问题
  • 原文地址:https://www.cnblogs.com/zydev/p/6165269.html
Copyright © 2020-2023  润新知