JavaWeb(六)

2.11 JSP 过滤器

JSP 和 Servlet 中的过滤器都是 Java 类。

过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息。

可以将一个或多个过滤器附加到一个 Servlet 或一组 Servlet。过滤器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 页面。

过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:

  • 在客户端的请求访问后端资源之前,拦截这些请求。
  • 在服务器的响应发送回客户端之前,处理这些响应。

过滤器通过 Web 部署描述符(web.xml)中的 XML 标签来声明,然后映射到您的应用程序的部署描述符中的 Servlet 名称或 URL 模式。

当 Web 容器启动 Web 应用程序时,它会为您在部署描述符中声明的每一个过滤器创建一个实例。

Filter 的执行顺序与在 web.xml 配置文件中的配置顺序一致,一般把 Filter 配置在所有的 Servlet 之前。

过滤器是一个实现了 javax.servlet.Filter 接口的 Java 类。javax.servlet.Filter 接口定义了三个方法:

序号 方法 & 描述
1 public void doFilter (ServletRequest, ServletResponse, FilterChain) 该方法完成实际的过滤操作,当客户端的请求与过滤器设置的 URL 匹配时,Servlet 容器将先调用过滤器的 doFilter 方法。FilterChain 用于访问后续过滤器。
2 public void init(FilterConfig filterConfig) web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
3 public void destroy() Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。

FilterConfig 使用

Filter 的 init 方法中提供了一个 FilterConfig 对象。

如 web.xml 文件配置如下:

<filter>
    <filter-name>LogFilter</filter-name>
    <filter-class>com.wyz.test.LogFilter</filter-class>
    <init-param>
        <param-name>Site</param-name>
        <param-value>无涯子博客</param-value>
    </init-param>
</filter>

在 init 方法使用 FilterConfig 对象获取参数:

public void  init(FilterConfig config) throws ServletException {
    // 获取初始化参数
    String site = config.getInitParameter("Site"); 
    // 输出初始化参数
    System.out.println("网站名称: " + site); 
}

JSP 过滤器实例

我们在请求和响应中可能会出现中文乱码情况,我们可以使用过滤器统一处理。

public class CharacterFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterFilter过滤器被初始化");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        System.out.println("CharacterFilter过滤器之前");
        chain.doFilter(request,response);
        System.out.println("CharacterFilter过滤器之后");
    }

    @Override
    public void destroy() {
        System.out.println("CharacterFilter过滤器被销毁");
    }
}

配置过滤器:

<filter>
    <filter-name>CharacterFilter</filter-name>
    <filter-class>com.wyz.CharacterFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CharacterFilter</filter-name>
    <url-pattern>/servlet/*</url-pattern>
</filter-mapping>

web.xml 中的 filter-mapping 元素的顺序决定了 Web 容器应用过滤器到 Servlet 的顺序。若要反转过滤器的顺序,您只需要在 web.xml 文件中反转 filter-mapping 元素即可。

过滤器简单应用

  • 乱码处理
  • 过滤拦截请求

我们很多网站都需要用户登录之后才能访问某些页面,没有登录则不能访问,会自动跳转到登录页面,这个功能就可以使用过滤器来实现。这里我们简单模拟一下:

<%-- 登录 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="${pageContext.request.contextPath}/sys/login" method="post">
        <label for="username">用户名</label>
        <input type="text" name="username" id="username"><br/>
        <input type="submit" value="提交">
    </form>
</body>
</html>

<%-- 主页 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
<a href="${pageContext.request.contextPath}/sys/logout">注销</a>
</body>
</html>

<%-- 错误页面 --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>登录失败,您的用户名错误</h1>
    <a href="${pageContext.request.contextPath}/sys/login.jsp">返回登录页面</a>
</body>
</html>
//处理登录请求的Servlet
public class SysLogin extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        String username = req.getParameter("username");
        if("admin".equals(username)){//登录成功
            session.setAttribute("USER_NAME",req.getSession().getId());
            resp.sendRedirect("/web01/sys/main.jsp");
        }else{
            //登录失败
            resp.sendRedirect("/web01/sys/error.jsp");
        }
    }
}

//退出登录
public class LogOut extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        if(session.getAttribute("USER_NAME") != null){
            session.removeAttribute("USER_NAME");//移出Session数据
        }
        //跳转到登录页面
        System.out.println("退出");
        resp.sendRedirect("/web01/sys/login.jsp");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

//过滤器
public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request1 = (HttpServletRequest) request;
        HttpServletResponse response1 = (HttpServletResponse) response;
        HttpSession session = request1.getSession();
        if(session.getAttribute("USER_NAME") == null){
            response1.sendRedirect("/web01/sys/login.jsp");
        }
        chain.doFilter(request1,response1);
    }

    @Override
    public void destroy() {

    }
}

在web.xml中配置:

<servlet>
    <servlet-name>SysLogin</servlet-name>
    <servlet-class>com.wyz.SysLogin</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>SysLogin</servlet-name>
    <url-pattern>/sys/login</url-pattern>
</servlet-mapping>
<servlet>
    <servlet-name>LogOut</servlet-name>
    <servlet-class>com.wyz.LogOut</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>LogOut</servlet-name>
    <url-pattern>/sys/logout</url-pattern>
</servlet-mapping>
<filter>
    <filter-name>LoginFilter</filter-name>
    <filter-class>com.wyz.LoginFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/sys/main.jsp</url-pattern>
</filter-mapping>

3. 文件上传

依赖引入:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

前端编写:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
    <title>文件上传测试</title>
</head>
<body>
<h1>文件上传测试</h1>
<form action="${pageContext.request.contextPath}/uploadServlet" method="post" enctype="multipart/form-data">
    <label for="uploadFile">选择一个文件</label>
    <input type="file" name="uploadFile" id="uploadFile"><br/>
    <input type="submit" value="上传">
</form>
</body>
</html>
  • 表单 method 属性应该设置为 POST 方法,不能使用 GET 方法。
  • 表单 enctype 属性应该设置为 multipart/form-data

后端编写:

public class Upload extends HttpServlet {
    private static final long serialVersionUID = 1L;
    //上传文件保存目录
    private static final String UPLOAD_DIRECTORY = "upload";
    //上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 50; // 50MB

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");
        //检查是否为多媒体上传
        if(!ServletFileUpload.isMultipartContent(req)){
            //不是则停止
            PrintWriter out = resp.getWriter();
            out.write("Error:表单必须包含enctype=multipart/form-data");
            out.flush();
            return;
        }
        // 配置上传参数
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
        factory.setSizeThreshold(MEMORY_THRESHOLD);
        // 设置临时存储目录
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

        ServletFileUpload upload = new ServletFileUpload(factory);

        // 设置最大文件上传值
        upload.setFileSizeMax(MAX_FILE_SIZE);
        // 设置最大请求值 (包含文件和表单数据)
        upload.setSizeMax(MAX_REQUEST_SIZE);
        // 中文处理
        upload.setHeaderEncoding("UTF-8");

        // 构造临时路径来存储上传的文件
        // 这个路径相对当前应用的目录
        String uploadPath = getServletContext().getRealPath("/") + File.separator + UPLOAD_DIRECTORY;

        // 如果目录不存在则创建
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }

        try{
            // 解析请求的内容提取文件数据
            List<FileItem> formItems = upload.parseRequest(req);

            if (formItems != null && formItems.size() > 0) {
                // 迭代表单数据
                for (FileItem item : formItems) {
                    // 处理不在表单中的字段
                    if (!item.isFormField()) {
                        String fileName = new File(item.getName()).getName();
                        String filePath = uploadPath + File.separator + fileName;
                        File storeFile = new File(filePath);
                        // 在控制台输出文件的上传路径
                        System.out.println(filePath);
                        // 保存文件到硬盘
                        item.write(storeFile);
                        req.setAttribute("message",
                                "文件上传成功!");
                    }
                }
            }

        }catch(Exception e){
           req.setAttribute("message",e.getMessage());
        }
        //请求转发跳转
        req.getRequestDispatcher("/message.jsp").forward(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

上传之后跳转页面,显示上传结果:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
    <title>文件上传结果</title>
    <meta charset="UTF-8">
</head>
<body>
<h2>${message}</h2>
</body>
</html>

posted @ 2021-12-23 14:46  无涯子wyz  阅读(53)  评论(0)    收藏  举报