• 17用filter实现全栈乱码过滤 和30天自动登录


           1. 全站乱码过滤

                  在整个EasyMall项目中,有多处都需要进行乱码处理,这些内容可以提取到一个模块中,这个模块可以是一个过滤器。

                  过滤器需要将请求与响应中的乱码进行处理。

                  a. 处理方式:

                         i. 响应乱码

                         response.setContentType("text/html;charset=utf-8");

                         ii. 请求乱码

                                分get与post两种情况。

                                如果为post请求,则只需:request.setCharacterEncoding("utf-8");

                                如果为get请求,则需要将每一个参数的乱码进行处理。

                                 并且如果将参数取出之后再进行处理,那么下一个request 的参数还需要再次处理,也不能确定需要处理的参数都有哪些,所以应该将原有request对象身上的参数处理完成,再设置回原有request身上才行。

                         iii. 解决方案:

                                1) 继承:可以重写方法但是不是修改的原有类中的方法,不符合需求。

                                2) 装饰者模式:是修改原有类中的方法,满足需求。

                                3) 动态代理:自行了解。

    装饰类就是我们写的,通过装饰类的构造函数来接收装饰类的对象

                  b. 代码实现:

    创建EncodingFilter.java

    package com.easymall.filter;
                    
                    import java.io.IOException;
                    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.ServletRequest;
                    import javax.servlet.ServletResponse;
                    import javax.servlet.http.HttpServletRequest;
                    
                    public class EncodingFilter implements Filter {
                            String encode = null;
                            boolean use_encode ;
                            public void init(FilterConfig filterConfig) throws ServletException {
                                    //在当前过滤器配置信息对象的身上,
                                    //可以引入代表web应用的对象servletContext,这样即可获取全局配置信息
                                    encode = filterConfig.getServletContext().getInitParameter("encode");
                                    //读取字符集是否使用的开发
                                    use_encode = Boolean.parseBoolean(filterConfig.getServletContext().getInitParameter("use_encode"));
                    
                            }
                            
                            public void doFilter(ServletRequest request, ServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
                                    //1.请求乱码处理post   
                    //        request.setCharacterEncoding("utf-8");
                            //get请求乱码处理
                            HttpServletRequest req = (HttpServletRequest) (use_encode?//use_encode是是否使用编码的开关,如果为true就说明tomcat配置的编码格式和我要求的不一样是iso8859-1我要用全站乱//码解析,如果不为true就代表tomcat的编码格式配置好了 utf-8不需要再做修改所以是正常的request 而不是装饰者的request
     new MyHttpServletRequest((HttpServletRequest) request,encode):request); //红色返回的是HTTPservletrequestWRAP的对象 可以用
    HTTPservletrequest接住
    //2.响应乱码 response.setContentType("text/html;charset="+encode); //放行  chain.doFilter(req, response); } public void destroy() { } }

    添加web.xml配置

    <!-- 全站乱码过滤器 -->
      <filter>
          <filter-name>EncodingFilter</filter-name>
          <filter-class>com.easymall.filter.EncodingFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>EncodingFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

    创建MyHttpServletRequest类

                    package com.easymall.filter;
                    
                    import java.util.HashMap;
                    import java.util.Map;
                    
                    import javax.servlet.http.HttpServletRequest;
                    import javax.servlet.http.HttpServletRequestWrapper;
                    
                    public class MyHttpServletRequest extends HttpServletRequestWrapper{  //本来实现的是HttpServletRequest接口,但是其要实现的方法太多了,我们只要实现获取参数的方法,更改参数中的乱码就行,所以我们采用HttpServletResquestWapper 他是HttpServletRequestWrapper 子实现抽象接口
                    
                            HttpServletRequest request = null;
                            String encode = null;
                            public MyHttpServletRequest(HttpServletRequest request,String encode) {
                                    super(request);
                                    this.request = request;
                                    this.encode = encode;
                                    
                            }
                            
                            @Override
                            public Map<String,String[]> getParameterMap() {
                                    //将原有map中的参数取出,处理乱码之后放入新的map中,并且返回新map
                                    Map<String,String[]> map = request.getParameterMap();
                                    //取出原map中的参数名和参数值,将处理后的参数值放入新map
                                    Map<String,String[]> rmap = new HashMap();
                                    //遍历原map,处理参数值乱码
                                    try {
                                            for(Map.Entry<String, String[]> entry:map.entrySet()){
                                                    String key = entry.getKey();//获取键名备用
                                                    String[] value = entry.getValue();//需要处理乱码
                                                    //遍历数组,将每一个值做乱码处理,再将乱码处理后的数据放入一个新的数组中。
                                                    String[] rvalue = new String[value.length];//创建一个与原数组长度相同的数组,来存储处理后的数据
                                                    for(int i=0;i<value.length;i++){//遍历数组中每一个元素
                                                            //处理数组中每一个元素的乱码,并放入新数组中
                                                            rvalue[i] = new String(value[i].getBytes("iso8859-1"),encode);
                                                    }
                                                    //将新数组添加到新map中
                                                    rmap.put(key, rvalue);
                                            }
                                            return rmap;
                                    } catch (Exception e) {
                                            throw new RuntimeException(e);
                                    }
                            }
                            @Override
                            public String[] getParameterValues(String name) {
                                    //获取乱码处理后的getParameterMap方法中的值,即当前方法所需结果
                                    Map<String,String[]> map = getParameterMap();
                                    return map.get(name);
                            }
                            @Override
                            public String getParameter(String name) {
                                    //上方方法的返回值是一个数组,取出数组中的第一个元素即可
                                    String[] values = getParameterValues(name);
                                    return  values!=null?values[0] : null; 
                            }
                            
                    }
                iv. 添加全局配置信息
                    <!-- 字符集选择 -->
                      <context-param>
                          <param-name>encode</param-name>
                          <param-value>utf-8</param-value>
                      </context-param>
                      <!-- 字符集使用开关 -->
                      <context-param>
                          <param-name>use_encode</param-name>
                          <param-value>true</param-value>
                      </context-param>

     二.30天自动登录

                  在EasyMall的登录页面,可以选择30天内容自动登录。

                  用户信息需要保存30天,使用session不合适,应该考虑将用户信息存入cookie中。

    由于整个网站的页面可能都会需要登录状态,所以可以将全部页面过滤,判断是否需要自动登录,过滤器可以满足需求。

    代码实现:

    创建loginFilter

                package com.easymall.filter;
                
                import java.io.IOException;
                import java.net.URLDecoder;
                
                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.Cookie;
                import javax.servlet.http.HttpServletRequest;
                
                import com.easymall.domain.User;
                import com.easymall.exception.MsgException;
                import com.easymall.service.UserService;
                
                public class LoginFilter implements Filter {
                        UserService userService = new UserService();
                        
                        public void init(FilterConfig filterConfig) throws ServletException {
                                
                
                        }
               
                        public void doFilter(ServletRequest request, ServletResponse response,
                                FilterChain chain) throws IOException, ServletException {
                                
                                HttpServletRequest req = (HttpServletRequest) request;//ServletRequest接口无法获得getCookie这个方法所以采用了他的子级接口HttpServletRequest来做强转
                                //读取cookie用户信息autologin
                                //1.获取全部cookie
                                Cookie[] cs = req.getCookies();     //获取到请求体中的cooies
                                //2.遍历cookie,从中寻找autologin,自动登录cookie
                                Cookie autologinC = null;
                                if(cs != null){
                                        for(Cookie c:cs){
                                                if("autologin".equals(c.getName())){
                                                        autologinC = c;
                                                }
                                        }
                                }
                                //找到了autologin,取出用户名和密码,与数据库中的数据比对
                                if(autologinC != null){
                                        //取出用户名密码
                                        String value = URLDecoder.decode(autologinC.getValue(), "utf-8");
                                        //value的组成应该为username+#+password,所以根据#切割
                                        String[] vs = value.split("#");
                                        String username = vs[0];
                                        String password = vs[1];
                                        try {
                                                //与数据库中的数据比对
                                                //由于在三层框架中userService服务层已经实现了登录功能,所以此处直接调用即可。
                                                User user = userService.loginUser(username, password);
                                                //保存登录状态--添加到session域
                                                req.getSession().setAttribute("user", user);
                                        } catch (MsgException e) {
                                                throw new RuntimeException(e);
                                        }
                                        
                                        
                                }
                                //放行
                                chain.doFilter(req, response);
                        }
                
                        public void destroy() {
                                
                
                        }
                
                }

    修改loginservlet

    package com.easymall.web;
    
    import java.io.IOException;
    import java.net.URLEncoder;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import com.easymall.domain.User;
    import com.easymall.service.UserService;
    import com.easymall.utils.JDBCUtils;
    import com.easymall.utils.MD5Utils;
    
    public class LoginServlet extends HttpServlet {
    
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
       //乱码处理
        //    request.setCharacterEncoding("utf-8");
            //response.setContentType("text/html;charset=utf-8");
            //1.获取参数
            String username=request.getParameter("username");
            String password=request.getParameter("password");
            String remname=request.getParameter("remname"); //"true"
            String autologin=request.getParameter("autologin"); 
            //2.记住用户名---cookie
            //remname 为"true"则表示要记住用户名。,反之为null 不需要记住用户名
            if("true".equals(remname)){
                Cookie cookie=new Cookie("remname",URLEncoder.encode(username,"utf-8") );
                cookie.setMaxAge(60*60*24*30);//30天记住用户名
                cookie.setPath(request.getContextPath()+"/");
                response.addCookie(cookie);    
            }
            else {
                Cookie cookie=new Cookie("remname", "");
                cookie.setMaxAge(0);//删除cookie所以设置时间为0
                cookie.setPath(request.getContextPath()+"/");
                response.addCookie(cookie);
            }
            //判断是否需要自动登录,如果需要则创建一个自动登录的cookie,保存用户信息30天
            if("true".equals(autologin))
            {
                Cookie cookie=new Cookie("autologin",     URLEncoder.encode(username+"#"+MD5Utils.md5(password), "UTF-8"));
                cookie.setMaxAge(60*60*24*30);
                cookie.setPath(request.getContextPath()+"/");
                response.addCookie(cookie);
            }
            //3.保存用户登录状态 ---session
            //判断用户名和密码是否匹配
        /*    Connection conn=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            try {
                conn=JDBCUtils.getConnection();
                ps=conn.prepareStatement("select * from user where username=? and password=?");
                ps.setString(1, username);
                ps.setString(2, password);
                rs=ps.executeQuery();
                if(rs.next()){//用户名和密码正确,完成登录
                    HttpSession session=request.getSession();
                    session.setAttribute("username", username);
                    
                }
                else { //返回登录页面做出提示
                    request.setAttribute("msg", "用户名或密码不正确");
                    request.getRequestDispatcher("/_login.jsp").forward(request, response);
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            finally{
                JDBCUtils.close(conn, ps, rs);
            }*/
            //传输数据到UserService
            UserService userService=new UserService();
            try {
                User user=userService.loginUser(username,MD5Utils.md5(password)); //因为需要登录成功后保存登录状态,那么返回值是查找到的user对象
            //得到user对象,放入session域 保持登录状态
                request.getSession().setAttribute("user", user);
            } catch (Exception e) {
                request.setAttribute("msg", e.getMessage());
                request.getRequestDispatcher("/_login.jsp").forward(request, response);
                return;
            }
            
            //4.跳转会首页
            response.sendRedirect(request.getContextPath()+"/");//跳转到不同服务器要加上域名 ,同一个服务器指定web应用
        }
    
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doGet(request, response);
    
        }
    
    }

    修改web.xml

                <!-- 30天自动登录过滤器 -->
                  <filter>
                      <filter-name>LoginFilter</filter-name>
                      <filter-class>com.easymall.filter.LoginFilter</filter-class>
                  </filter>
                  <filter-mapping>
                      <filter-name>LoginFilter</filter-name>
                      <url-pattern>/*</url-pattern>
                  </filter-mapping>
  • 相关阅读:
    C#操作XML配置文件
    Git详细命令
    ng : File C:UsersaronAppDataRoaming pm g.ps1 cannot be loaded because running
    Abstract抽象类 && Interface接口
    Markdown基本使用
    Scrapy基本使用
    request取值相关
    轮询与长轮询
    爬虫
    Flask相关组件及应用
  • 原文地址:https://www.cnblogs.com/xuwangqi/p/11380078.html
Copyright © 2020-2023  润新知