JavaWeb笔记-21- Filter案例 之 解决全站字符乱码、页面静态化 、day21思维导图

day21 思维导图

这里写图片描述

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


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

基本上在每个Servlet中都要处理乱码问题,所以应该把这个工作放到过滤器中来完成。

2.难点:处理GET请求参数的问题。

  原因:request只有getParameter(),而没有setParameter()方法。不能将编码后的字符放入request。

  解决:掉包request。
      1)在新的request中在servlet中重写getParameter()方法,直接完成编码处理。 (装饰者模式)
      2)返回新的request,在servlet中调用即可。

  而post请求中含有request.setCharacterEncoding()方法可直接设置

 掉包原理:使用装饰者模式

servlet

public class AServlet extends HttpServlet {

    //处理get参数编码
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        String username = request.getParameter("username");
        response.getWriter().println(username);
    }

    //处理post编码
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        String username = request.getParameter("username");
        response.getWriter().println(username);
    }
}

Filter

public class AFilter implements Filter {

    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        //用此方法处理POST请求编码问题
        request.setCharacterEncoding("utf-8");

        //处理GET请求编码的问题
        //不可行  原因:重新编码后的username无法放进request中,不存在setParameter方法
//      String username = request.getParameter("username");
//      username = new String(username.getBytes("ISO-8859-1"), "UTF-8");

        /*
         * 调包request
         *  
         *  原理:新的request中,getParameter方法被重写。
         *      在servlet中调用新的request,将自动完成处理编码
         * 
         * 步骤:
         * 1. 写一个request的装饰类
         * 2. 在放行时,使用我们自己的request
         */
        //转换request类型
        HttpServletRequest req = (HttpServletRequest) request;

        if(req.getMethod().equals("GET")) {

            //将原有的req传入 装饰类,
            //重写装饰类中getParameter()方法,此方法可完成处理编码。 
            //替换request。
            EncodingRequest er = new EncodingRequest(req);  
            chain.doFilter(er, response);   //放行新的request
        } else if(req.getMethod().equals("POST")) {
            chain.doFilter(request, response);
        }
    }
    public void init(FilterConfig fConfig) throws ServletException {
    }

}

/**
 * 装饰request
 * @author 一万年行不行
 */

//专门负责掉包时的类  此类帮我们重写了所有我们没有重写的方法
public class EncodingRequest extends HttpServletRequestWrapper {
    private HttpServletRequest req;

    public EncodingRequest(HttpServletRequest request) {
        super(request);   //传参进父类,在父类中完成构造
        this.req = request;   //替换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(e);
        }

        return value;
    }
}

2、案例四:页面静态化

1)什么是页面静态化:
    首次访问去数据库获取数据,然后把数据保存到一个html页面中
    二次访问,就不再去数据库获取了,而是直接显示html

2)原理:
    1.使用过滤器,把servlet请求的资源所做的输出保存到本地指定路径中,然后将请求重定向到html页面。
    2.二次访问时,这个html已经存在,那么直接重定向,不用再去访问servlet!

适用情景:很少发生变化的页面

步骤:
1)搭建背景环境(图书管理项目)

     写一个小项目,图书管理
    1.需要创建数据库
    2.导包 
    3.页面:
            * jsp:link.jsp
                链接页面,四个超链接:
                    > 查询所有
                    > 查看SE分类
                    > 查看EE分类
                    > 查看框架分类
              * show.jsp
                显示查询结果
    4.Servlet(继承BaseServlet):
            BookServlet
                  * findAll() --> 查看所有图书
                  * findByCategory --> 按分类进行查询

    5.BookService;略
     6.BookDao;
              * List<Book> findAll()
              * List<Book> findByCategory(int category)
    7.domain:Book类

Book:略

BookDao

public class BookDao {
    private QueryRunner qr = new TxQueryRunner();
    //查询所有
    public List<Book> findAll() {
        try {
            String sql = "select * from t_book";
            return qr.query(sql, new BeanListHandler<Book>(Book.class));
        } catch(SQLException e) {
            throw new RuntimeException(e);
        }
    }

    //通过等级查询
    public List<Book> findByCategory(int category) {
        try {
            String sql = "select * from t_book where category=?";
            return qr.query(sql, new BeanListHandler<Book>(Book.class), category);
        } catch(SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

Servlet

public class BookServlet extends BaseServlet {
    private BookDao bookDao = new BookDao();

    public String findAll(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //调用查询方法,并保存到request域中
        request.setAttribute("bookList", bookDao.findAll());
        return "f:/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 "f:/show.jsp";
    }
}

Filter

public class StaticFilter implements Filter {

    private FilterConfig config;
    public void destroy() {}
    public void init(FilterConfig fConfig) throws ServletException {
        this.config = fConfig;
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        //转换request、response类型
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        /*
         * 1. 第一次访问时,查找请求对应的html页面是否存在,如果存在重定向到html
         * 2. 如果不存在,放行!把servlet访问数据库后,输出给客户端的数据保存到一个html文件中
         *   再重定向到html
         */
        /*
         * 一、获取category参数!
         * category有四种可能:
         * * null --> null.html
         * * 1 --> 1.html
         * * 2 --> 2.html
         * * 3 --> 3.html
         * 
         * html页面的保存路径, htmls目录下
         * 
         * 判断对应的html文件是否存在,如果存在,直接重定向!
         */
        String category = request.getParameter("category");

        //得到对应的文件名称
        String htmlPage = category + ".html";

        //得到文件的存放目录
        String htmlPath = config.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。
         *  让reponse中的getWriter()与一个html文件绑定。
         *  那么show.jsp的输出就到了html文件中
         */
        //在StaticResponse中调用输出时,会根据参数给的路径和res(响应内容)自动生成html文件
        //返回一个新的响应
        StaticResponse sr = new StaticResponse(res, destFile.getAbsolutePath());

        //放行,即生成了html文件
        chain.doFilter(request, sr);

        // 这时页面已经存在,重定向到html文件,使客户端看到生成页面
        res.sendRedirect(req.getContextPath() + "/htmls/" + htmlPage);
    }
}

/**
 * 掉包response
 * @author 一万年行不行
 *
 */
public class StaticResponse extends HttpServletResponseWrapper {

    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);

        // 创建一个与html文件路径在一起的流对象
        // 会根据路径自动生成文件
        pw = new PrintWriter(path, "utf-8");
    }

    public PrintWriter getWriter() {
        // 返回一个与html绑定在一起的printWriter对象
        // jsp会使用它进行输出,这样数据都输出到html文件了。
        return pw;
    }
}
问题:通过show.jsp生成的html文件会中文乱码

原因:文件头中未声明编码类型

解决: 在show.jsp页面文件头中添加语句声明
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_41307491/article/details/81707229
今日推荐