Java学习路线-49:Servlet过滤器Filter
课时1 过滤器的入门
JavaWeb三大组件
1、都需要在web.xml中进行配置
Servlet
Filter
Listener
2、过滤器
会在一组资源(jsp, servlet, css, html等等)的前面执行
可以让请求得到目标资源,也可以不让请求达到
过滤器有拦截请求的能力
3、编写过滤器
(1)实现Filter接口
(2)在web.xml中进行配置
(3)Filter是单例的
4、配置web.xml
<web-app><filter><filter-name>FilerName</filter-name><filter-class>FilerClass</filter-class></filter><filter-mapping><filter-name>FilerName</filter-name><url-pattern>/*</url-pattern></filter-mapping>
</web-app>
继承示例
package com.pengshiyu.filtrer;import javax.servlet.*;
import java.io.IOException;public class Afilter implements Filter {/*** 创建之后马上执行,用来做初始化*/@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}/*** 每次过滤都会执行*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("进入过滤器");// 调用后序方法filterChain.doFilter(servletRequest, servletResponse);System.out.println("离开过滤器");}/*** 销毁之前的调用,用来释放资源*/@Overridepublic void destroy() {}
}
FilterConfig -> 与ServletConfig相似
获取初始化参数 getInitParameter()
获取过滤器名称 getFilterName()
获取application getServletContext()
FilterChain
放行,执行后序方法 doFilter()
课时2 多个过滤器的执行顺序
执行下一个过滤器或目标资源
FilterChain.doFilter()
Afilter进入过滤器
Bfilter进入过滤器
getAge
Bfilter离开过滤器
Afilter离开过滤器
课时3 四种拦截方式
请求 REQUEST 默认
转发 FORWARD
包含 INCLUDE
错误 ERROR
<filter-mapping><filter-name>FilerName</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher>
</filter-mapping>
页面出错
<error-page><error-code>500</error-code><location>500.html</location>
</error-page>
课时4 使用filter-mapping控制多个Filter的执行顺序
filter-mapping的配置顺序决定过滤器执行顺序
课时5 Filter的应用场景、Filter的目标资源、小结
预处理:执行目标资源之前做预处理工作,例如设置编码
拦截:通过条件判断是否放行,例如用户登录校验
回程拦截:目标资源执行之后,做一些后序的特殊处理工作,例如目标资源输出的数据进行处理
直接指定servlet-name
<filter-mapping><filter-name>FilerName</filter-name><servlet-name>ServletName</servlet-name>
</filter-mapping>
小结
Filter3个方法
FilterChain类
4中拦截方式
课时6 案例1:分IP统计访问次数
数据结构:
ip | count |
---|---|
192.168.0.1 | 32 |
192.168.0.2 | 22 |
统计工作在所有资源之前都执行,使用Filter
这个过滤器只做统计,不做拦截
数据Map<String, Integer>
Map保存到ServletContext中
从request中获取客户端ip
使用监听器创建 map
AListener.java
package com.pengshiyu.listener;import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.LinkedHashMap;
import java.util.Map;public class AListener implements ServletContextListener {// 服务器启动时创建mappublic void contextInitialized(ServletContextEvent sce) {Map<String, Integer> map = new LinkedHashMap<String, Integer>();sce.getServletContext().setAttribute("map", map);}public void contextDestroyed(ServletContextEvent sce) {}
}
使用过滤器统计数据
AFilter.java
package com.pengshiyu.filter;import javax.servlet.*;
import java.io.IOException;
import java.util.Map;public class AFilter implements Filter {private FilterConfig config;/*** 创建之后马上执行,用来做初始化*/@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.config = filterConfig;}/*** 每次过滤都会执行*/@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {ServletContext app = this.config.getServletContext();Map<String, Integer> map = (Map<String, Integer>)app.getAttribute("map");String ip = request.getRemoteAddr();System.out.println("ip: " + ip);if(map.containsKey(ip)){Integer count = map.get(ip);map.put(ip, count+1);} else{map.put(ip, 1);}// 放行filterChain.doFilter(request, response);}/*** 销毁之前的调用,用来释放资源*/@Overridepublic void destroy() {}
}
显示数据
BServlet.java
package com.pengshiyu.servlet;import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;public class BServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {ServletContext app = getServletContext();Map<String, Integer> map = (Map<String, Integer>) app.getAttribute("map");response.setContentType("text/html; charset=UTF-8");response.getWriter().println(map.toString());}
}
配置监听器和过滤器生效
web.xml
<?xml version="1.0" encoding="utf-8"?><web-app><servlet><servlet-name>BServlet</servlet-name><servlet-class>com.pengshiyu.servlet.BServlet</servlet-class></servlet><servlet-mapping><servlet-name>BServlet</servlet-name><url-pattern>/b</url-pattern></servlet-mapping><filter><filter-name>AFilter</filter-name><filter-class>com.pengshiyu.filter.AFilter</filter-class></filter><filter-mapping><filter-name>AFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><listener><listener-class>com.pengshiyu.listener.AListener</listener-class></listener>
</web-app>
课时7 案例2:粗粒度权限管理
基于角色的权限控制RBAC
tb_user
tb_role
tb_userrole
tb_menu
tb_rolemenu
web.xml
<?xml version="1.0" encoding="utf-8"?><web-app><servlet><servlet-name>AServlet</servlet-name><servlet-class>com.pengshiyu.servlet.AServlet</servlet-class></servlet><servlet-mapping><servlet-name>AServlet</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping><filter><filter-name>AFilter</filter-name><filter-class>com.pengshiyu.filter.AFilter</filter-class></filter><filter-mapping>
<!-- 不能将过滤器设置在login.html上,不然没法登录了--><filter-name>AFilter</filter-name><url-pattern>/hello.html</url-pattern></filter-mapping></web-app>
AServlet.java
package com.pengshiyu.servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class AServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");System.out.println("post: " + username);// 设置sessionrequest.getSession().setAttribute("username", username);// 跳转页面request.getRequestDispatcher("hello.html").forward(request, response);}
}
过滤器进行简单的权限校验
AFilter.java
package com.pengshiyu.filter;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;public class AFilter implements Filter {private FilterConfig config;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.config = filterConfig;}@Overridepublic void doFilter(ServletRequest req, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)req;String username = (String) request.getSession().getAttribute("username");System.out.println("filter: " + username);if(username != null){// 放行filterChain.doFilter(request, response);} else{// 跳转到登录页request.getRequestDispatcher("login.html").forward(request, response);}}@Overridepublic void destroy() {}
}
课时8 案例3:全站编码问题
// post编码
request.setCharacterEncoding("utf-8");// get编码
String username = request.getParameter("username");
username = new String(username.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);// 响应编码
response.setContentType("text/html; charset=UTF-8");
HttpServletRequest装饰类
EncodingRequest.java
package com.pengshiyu.filter;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.nio.charset.StandardCharsets;// 装饰器
public class EncodingRequest extends HttpServletRequestWrapper {public EncodingRequest(HttpServletRequest request) {super(request);}@Overridepublic String getParameter(String name) {// 处理编码问题String value = super.getParameter(name);value = new String(value.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);return value;}
}
过滤器AFilter.java
package com.pengshiyu.filter;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;public class AFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) request;String method = httpServletRequest.getMethod();// 设置响应编码response.setContentType("text/html; charset=UTF-8");if ("GET".equals(method)) {// 放行EncodingRequest encodingRequest = new EncodingRequest(httpServletRequest);filterChain.doFilter(encodingRequest, response);} else if ("POST".equals(method)) {request.setCharacterEncoding("utf-8");filterChain.doFilter(request, response);}}@Overridepublic void destroy() {}
}
响应处理AServlet.java
package com.pengshiyu.servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class AServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println(request.getParameter("name"));response.getWriter().print("你好");}
}
web.xml
<?xml version="1.0" encoding="utf-8"?><web-app><!-- 注册 Servlet,帮助web服务器反射该类 --><servlet><servlet-name>AServlet</servlet-name><servlet-class>com.pengshiyu.servlet.AServlet</servlet-class></servlet><!-- 映射 Servlet 资源,用url-pattern元素标示 URL --><servlet-mapping><servlet-name>AServlet</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping><filter><filter-name>AFilter</filter-name><filter-class>com.pengshiyu.filter.AFilter</filter-class></filter><filter-mapping>
<!-- 不能将过滤器设置在login.html上,不然没法登录了--><filter-name>AFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
</web-app>
课时9 案例4:页面静态化之准备工作(图书管理小项目)
功能:
查询所有
按分类查看BookServletfindAll() 查询全部findByCategory() 按分类查询BookService: 省略BookDao:List<Book> findAll()List<Book> findByCategory()Book:bidbnamepricecategory
静态化:
第一次访问从数据库取数据,保存到html中
第二次之后访问就直接从html中读取,不再从数据库中取数据
数据准备:
create table tb_book(bid int primary key auto_increment,bname varchar(50),price decimal(10, 2),category int
);insert into tb_book(bname, price, category) values("Java", 12, 1);
insert into tb_book(bname, price, category) values("Python", 12, 1);
insert into tb_book(bname, price, category) values("JavaScript", 12, 1);
insert into tb_book(bname, price, category) values("Go", 12, 1);insert into tb_book(bname, price, category) values("三国演义", 12, 2);
insert into tb_book(bname, price, category) values("西游记", 12, 2);
insert into tb_book(bname, price, category) values("水浒传", 12, 2);
insert into tb_book(bname, price, category) values("红楼梦", 12, 2);
创建对应的Book类
package com.pengshiyu.bean;public class Book {private int bid;private String bname;private double price;private int category;public Book() {}public int getBid() {return bid;}public void setBid(int bid) {this.bid = bid;}public String getBname() {return bname;}public void setBname(String bname) {this.bname = bname;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public int getCategory() {return category;}public void setCategory(int category) {this.category = category;}@Overridepublic String toString() {return "Book{" +"bid=" + bid +", bname='" + bname + '\'' +", price=" + price +", category=" + category +'}';}
}
BookDao.java
package com.pengshiyu.dao;import com.pengshiyu.bean.Book;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import util.TxQueryRunner;import java.sql.SQLException;
import java.util.List;public class BookDao {private QueryRunner qr = new TxQueryRunner();public List<Book> findAll() {String sql = "select * from tb_book";try {List<Book> list = qr.query(sql, new BeanListHandler<Book>(Book.class));System.out.println(list);return list;} catch (SQLException e) {throw new RuntimeException(e);}}public List<Book> findByCategory(int category) {String sql = "select * from tb_book where category = ?";try {return qr.query(sql, new BeanListHandler<Book>(Book.class), category);} catch (SQLException e) {throw new RuntimeException(e);}}
}
BookServlet
package com.pengshiyu.servlet;import com.pengshiyu.dao.BookDao;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class BookServlet extends BaseServlet {private BookDao bookDao = new BookDao();public void findAll(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {request.setAttribute("bookList", bookDao.findAll());request.getRequestDispatcher("book.jsp").forward(request, response);}public void findByCategory(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int category = Integer.parseInt(request.getParameter("category"));request.setAttribute("bookList", bookDao.findByCategory(category));request.getRequestDispatcher("book.jsp").forward(request, response);}
}
用到的工具类 TxQueryRunner.java
package util;import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;public class TxQueryRunner extends QueryRunner {@Overridepublic int[] batch(String sql, Object[][] params) throws SQLException {Connection con = JdbcUtil.getConnection();int[] result = super.batch(con, sql, params);JdbcUtil.releaseConnection(con);return result;}@Overridepublic <T> T query(String sql, ResultSetHandler<T> rsh, Object... params)throws SQLException {Connection con = JdbcUtil.getConnection();T result = super.query(con, sql, rsh, params);JdbcUtil.releaseConnection(con);return result;}@Overridepublic <T> T query(String sql, ResultSetHandler<T> rsh) throws SQLException {Connection con = JdbcUtil.getConnection();T result = super.query(con, sql, rsh);JdbcUtil.releaseConnection(con);return result;}@Overridepublic int update(String sql) throws SQLException {Connection con = JdbcUtil.getConnection();int result = super.update(con, sql);JdbcUtil.releaseConnection(con);return result;}@Overridepublic int update(String sql, Object param) throws SQLException {Connection con = JdbcUtil.getConnection();int result = super.update(con, sql, param);JdbcUtil.releaseConnection(con);return result;}@Overridepublic int update(String sql, Object... params) throws SQLException {Connection con = JdbcUtil.getConnection();int result = super.update(con, sql, params);JdbcUtil.releaseConnection(con);return result;}
}
JdbcUtil.java
package util;import com.mchange.v2.c3p0.ComboPooledDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;public class JdbcUtil {// 需要配置c3p0-config.xmlprivate static ComboPooledDataSource dataSource = new ComboPooledDataSource();// 返回连接对象public static Connection getConnection() {try {return dataSource.getConnection();} catch (SQLException e) {throw new RuntimeException(e);}}// 返回连接池对象public static DataSource getDataSource() {return dataSource;}// 释放连接public static void releaseConnection(Connection connection) {try {connection.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
book.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><h2>图书列表</h2>
分类:
<a href="book?method=findAll">全部</a>
<a href="book?method=findByCategory&category=1">第一类</a>
<a href="book?method=findByCategory&category=2">第二类</a><table border="1"><tr><th>ID</th><th>书名</th><th>价格</th><th>分类</th></tr><c:forEach items="${bookList}" var="book"><tr><td>${book.bid}</td><td>${book.bname}</td><td>${book.price}</td><td>${book.category}</td></tr></c:forEach>
</table>
配置文件
pom.xml
<dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version>
</dependency>
<dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version>
</dependency>
web.xml
<servlet-mapping><servlet-name>BookServlet</servlet-name><url-pattern>/book</url-pattern>
</servlet-mapping><servlet><servlet-name>BookServlet</servlet-name><servlet-class>com.pengshiyu.servlet.BookServlet</servlet-class>
</servlet>
c3p0-config.xml
<?xml version="1.0" encoding="utf-8"?>
<c3p0-config><!-- 这是默认配置信息 --><default-config><!-- 连接四大参数配置 --><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/data</property><property name="user">root</property><property name="password">123456</property><!-- 池参数配置 --><property name="acquireIncrement">2</property><property name="initialPoolSize">2</property><property name="minPoolSize">2</property><property name="maxPoolSize">10</property></default-config>
</c3p0-config>
访问路径
http://localhost:8080/demo/book?method=findAll
http://localhost:8080/demo/book?method=findByCategory&category=1
课时10 案例4:页面静态化之如果文件存在直接重定向到html
使用一个过滤器,把servlet请求的资源输出保存到html中
第二次访问资源的时候,如果已存在就直接重定向到html文件
课时11 案例5:页面静态之生成html页面
CacheFilter.java
package com.pengshiyu.filter;import com.pengshiyu.response.StaticResponse;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;public class CacheFilter implements Filter {private FilterConfig config;private final String cacheFileName = "cache";private String cacheFilePath = null;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.config = filterConfig;this.cacheFilePath = this.config.getServletContext().getRealPath(this.cacheFileName);File file = new File(this.cacheFilePath);if(file.exists()){file.mkdir();}}/*** 访问路径* http://localhost:8080/demo/book?method=findByCategory&category=4*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse)servletResponse;String category = request.getParameter("category");String filepath = this.cacheFilePath + "/" + category + ".html";File file = new File(filepath);// 如果页面不存在就缓存页面if(!file.exists()){StaticResponse staticResponse = new StaticResponse(response, filepath);filterChain.doFilter(request, staticResponse);}System.out.println("文件存在了");request.getRequestDispatcher(this.cacheFileName + "/" + category + ".html").forward(request, response);}@Overridepublic void destroy() {}
}
StaticResponse.java
package com.pengshiyu.response;import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;public class StaticResponse extends HttpServletResponseWrapper {private PrintWriter pw;public StaticResponse(HttpServletResponse response, String filename) throws FileNotFoundException {super(response);this.pw = new PrintWriter(filename);}@Overridepublic PrintWriter getWriter() throws IOException {// 掉包输出流return this.pw;}
}
Java学习路线-49:Servlet过滤器Filter相关推荐
- [转]从入门到精通,Java学习路线导航
引言 最近也有很多人来向我"请教",他们大都是一些刚入门的新手,还不了解这个行业,也不知道从何学起,开始的时候非常迷茫,实在是每天回复很多人也很麻烦,所以在这里统一作个回复吧. J ...
- 【最新版】Java学习路线(含B站口碑推荐视频链接)
文章目录 关于如何自学 一.计算机网络 二.数据结构与算法 三.操作系统 四.计算机组成原理 五.编译原理 六.设计模式 七.MySQL 八.实操工具 九.JAVA并发与JVM 十.Redis 十一. ...
- 这可能是最全面的Java学习路线了
大家好,我是大彬~ 我本科学的不是计算机,大四开始自学Java,并且拿到了几个互联网中大厂的offer.在学习Java这方面还是比较有经验的,下面我来分享下我整理的Java自学路线. 在这里也提醒学弟 ...
- 从入门到精通,Java学习路线导航
引言 最近也有很多人来向我"请教",他们大都是一些刚入门的新手,还不了解这个行业,也不知道从何学起,开始的时候非常迷茫,实在是每天回复很多人也很麻烦,所以在这里统一作个回复吧. J ...
- 从入门到精通,Java学习路线导航(附学习资源)
引言 最近也有很多人来向我"请教",他们大都是一些刚入门的新手,还不了解这个行业,也不知道从何学起,开始的时候非常迷茫,实在是每天回复很多人也很麻烦,所以在这里统一作个回复吧. J ...
- 从入门到精通,Java学习路线导航(附学习资料+持续更新)
引言 最近也有很多人来向我"请教",他们大都是一些刚入门的新手,还不了解这个行业,也不知道从何学起,开始的时候非常迷茫,实在是每天回复很多人也很麻烦,所以在这里统一作个回复吧. J ...
- Java学习路线详解
如今互联网行业发展火爆,各大企业对于[Java开发请添加链接描述](http://www.suzxms.com.cn/java/)人才的需求也在不断增加,很多刚毕业的同学找不到合适的工作,想学习一门赖 ...
- B站有哪些值得Java初学者看的视频,Java学习路线
我的读者中有很大一部分学生读者,以前也分享过一些Java学习路线,但是我收到的反馈并不好,因为学习路线包含的内容太多了,对于初学者来说难度太大,时间也不够用,根本学不完.今天我将结合B站优秀视频整理一 ...
- 十年架构师留下最完整的Java学习路线
原文地址:https://club.dingding.xin/topic/5081/十年架构师留下最完整的java学习路线?code=cb850abbce523c7f886f583d6dc00f5e ...
最新文章
- 发布一个验证码生成组件
- 全国默哀 网站首页都要变成灰色的简单解决办法
- 解决Eclipse代码分析插件SonarLint在Console输出乱码问题
- 年轻工程师如何锻炼成高手的
- ubuntu终端彻底删除软件
- 东北大学c语言及程序设计,东大20秋学期《C语言及程序设计》在线平时作业1参考...
- Impala之DDL、DML
- 单webview上拉刷新下拉加载
- 修改服务器控件的ID和Name
- 计算机丢失disrupt,disrupt造句
- android 获取高德地图坐标,获取地址描述数据-获取地图数据-开发指南-Android 地图SDK | 高德地图API...
- 编程珠玑第一章-位图压缩存储
- 【Kay】Java多线程
- ASP微信头像保存到服务器,asp微信小程序获取用户头像和微信名-asp写的服务端...
- 局部替换算法最小生成树
- 思科无线POC测试要包含哪些测试项
- RPG Maker mv框架代码解析之Sprite_Button
- Cocos Creator 超简洁代码实现有限状态机 FSM,打造丝滑角色动作
- 计算机开机怎么设置网络连接,电脑怎么设置开机自动连接宽带
- 整理下使用yum localinstall做离线安装的点