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>
原文地址:https://www.cnblogs.com/xuwangqi/p/11380078.html