目录
Filter 过滤器
Filter:一个实现了特殊接口(Filter)的Java类. 实现对请求资源(jsp,servlet,html,)的过滤的功能. 过滤器是一个运行在服务器的程序, 优先于请求资源(Servlet或者jsp,html)之前执行. 过滤器是javaweb技术中最为实用的技术之一
Filter的作用是对目标资源(Servlet,jsp)进行过滤,其应用场景有: 登录权限检查,解决网站乱码,过滤敏感字符等等。对请求进行过滤,本质是一个接口。
一、通过Fliter解决乱码问题
1、编写一个类去实现 Filter 接口
2、实现过滤方法 doFilter()
3、到 web.xml 中去配置 Filter 的拦截路径
Filter
public class EncodingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("------------- 到达EncodingFilter -------------");
//解决乱码
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//请求放行 执行目标资源
chain.doFilter(request,response);
System.out.println("------------- 离开EncodingFilter -------------");
}
}
配置编码过滤器 (web.xml)
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.atguigu.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/filter01</url-pattern>
</filter-mapping>
servlet
@WebServlet("/filter01")
public class Filter01Servlet extends HttpServlet {
//使用Filter解决乱码问题
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("----- 请求:Filter01Servlet -----");
String username = req.getParameter("username");
System.out.println("username = " + username);
resp.getWriter().println("成功");
}
}
html
<form action="filter01" method="post">
<span>解决乱码</span><br>
<span>用户名: <input type="text" name="username"> </span><br>
<input type="submit"> <br>
</form>
二、Filter的生命周期
生命周期阶段 | 执行时机 | 生命周期方法 |
---|---|---|
创建对象 | Web服务器启动时 | init(),通常在该方法中做初始化工作 |
拦截请求 | 来一次请求执行一次 | doFilter(),通常在该方法中执行拦截过滤 |
销毁 | Web程序卸载时 | destroy(),通常在该方法中执行资源释放 |
回顾 servlet声明周期:
Servlet
init() 当请求需要此Servlet 处理时
<load-on-startup>x</load-on-startup> 设置初始化时机,x值越小启动越早。
service() 来一次请求执行一次
destory() 程序卸载的时
三、Filter 的拦截路径
过滤器匹配的目的是指定当前过滤器要拦截哪些资源
精确匹配 精确匹配
<url-pattern>/filter01</url-pattern>
以上配置的路径,表示请求地址必须为:http://ip:port/工程路径/target.jsp
Servlet名称 匹配
<servlet-name>Target01Servlet</servlet-name>
目录匹配 目录匹配
<url-pattern>/admin/*</url-pattern>
请求地址必须为:http://ip:port/工程路径/admin/*(以admin开头)
后缀名匹配 后缀名匹配(不能以斜杆打头)
<url-pattern>*.html</url-pattern>
以上配置的路径,表示请求地址必须以: .html结尾才会拦截到
不在乎.后面写的什么东西,↓↓↓不管是.action还是.abc结尾等都认
<url-pattern>*.do</url-pattern>
以上配置的路径,表示请求地址必须以.do 结尾才会拦截到
<url-pattern>*.action</url-pattern>
以上配置的路径,表示请求地址必须以.action 结尾才会拦截到
Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在
四、过滤器匹配规则
一个资源被多个过滤器过滤,执行顺序:
如果采用 <url-pattern> 方式配置 ,按照配置顺序执行。
如果采用 <servlet-name> 方式配置,该过滤器最后执行。
过滤器链 (责任链模式)
有一种设计模式:责任链模式
多个过滤器组成的链条(chain)。
一个请求可能被多个过滤器所过滤,只有当所有过滤器都放行,请求才能到达目标资源。如果有某一个过滤器没有放行,那么请求则无法到达后续过滤器以及目标资源,多个过滤器组成的链路就是过滤器链。
五、 应用:敏感字屏蔽
过滤器
public class commonFilter implements Filter {
//敏感字集合
ArrayList<String> list = null;
//filter初始化时(启动web服务器)
public void init(FilterConfig config) throws ServletException {
try {
//1.在Filter初始化时,通过各种流,解决敏感,读取敏感字文件
InputStream is = commonFilter.class.getClassLoader().getResourceAsStream("common");
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
//BufferedReader 方便读取一行操作 readLine()
BufferedReader br = new BufferedReader(isr);
//2.读取敏感字
list = new ArrayList<>();
String line = "";
while ((line = br.readLine())!=null){
//按照空格分割
String[] array = line.split(" ");
for (String s : array) {
//将每一个独立的敏感字符串添加到集合内
list.add(s);
}
}
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
}
}
public void destroy() {
}
//匹配路径被访问后
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("----- commonFilter -----");
//准备工作
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)resp;
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//1.获取评论
String common = request.getParameter("common");
boolean falg = false;
//2.判断是否包含敏感字
for (String s : list) {
if(common.contains(s)){
falg=true;
break;
}
}
//3.如果包含屏蔽,如果不包含放行
if(falg){
response.getWriter().println("屏蔽啦");
}else {
chain.doFilter(request,response);
}
}
}
<filter>
<filter-name>commonFilter</filter-name>
<filter-class>com.atguigu.filter.commonFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>commonFilter</filter-name>
<url-pattern>/filter03</url-pattern>
</filter-mapping>
Listener 监听器
只要触发了监听器条件,就会触发对应的Listener。
Request
ServletRequestListener (请求创建和销毁)
ServleRequestAttributeListener (属性的设置、获取、修改)
Session
HttpSessionListener (session的创建和销毁)
HttpSessionAttributeListener (session的设置、获取、修改)
HttpSessionBindingListener (处理session对象监听器绑定和解绑定接口)
HttpSessionActivationListener (处理session对象钝化和活化状态接口)
Application
ServletContextListener (ServletContext 的创建和销毁)
ServletContextAttributeListener (对属性值的设置、获取、修改)
<!-- 注册监听器-->
<listener>
<listener-class>com.atguigu.listener.MyRequestLister</listener-class>
</listener>
public class MyRequestLister implements ServletRequestListener, ServletRequestAttributeListener {
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("请求销毁了.......");
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
String uname = servletRequestEvent.getServletRequest().getParameter("uname");
System.out.println("请求初始化了:"+ uname);
}
@Override
public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
System.out.println("添加属性了");
String name = servletRequestAttributeEvent.getName();
Object value = servletRequestAttributeEvent.getValue();
System.out.println(name + "-->" + value);
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
}
}
一、Session 的活化与钝化
钝化 :将session存储到磁盘上,服务器关闭时钝化。
活化:将磁盘中的 session 加载到程序(内存)内,第一次使用session时活化。
需要在web目录下创建 META-INF ,context.xml文件,配置存储的目录
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Manager className="org.apache.catalina.session.PersistentManager">
<!--session钝化存储的路径-->
<Store className="org.apache.catalina.session.FileStore" directory="d:/session"/>
</Manager>
</Context>
如果session内有对象数据,必须实现Serializable接口。否则无法钝化(不报错)。
需要将监听器与session对象进行绑定:将对应监听器添加到session域内
session.setAttribute ("listener", new MySessionActiveListener());
public class MySessionActiveListener implements HttpSessionActivationListener {
@Override//钝化
public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
System.out.println(httpSessionEvent.getSession().getId() + " session 即将钝化");
}
@Override//活化
public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
System.out.println(httpSessionEvent.getSession().getId() + " session 已经活化");
}
}
@WebServlet("/set")
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("--- set ---");
HttpSession session = req.getSession();
System.out.println(session.getId()+" isNew:"+session.isNew());
session.setAttribute("string","abc");
//将监听器与 session绑定
session.setAttribute("listener", new MySessionActiveListener());
}
}
@WebServlet("/get")
public class Servlet2 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("--- get ---");
HttpSession session = req.getSession();
String string = (String) session.getAttribute("string");
System.out.println(session.getId()+" isNew:"+session.isNew());
System.out.println(string);
}
}
二、观察者模式简介
观察者模式是二十三中设计模式之一,它是指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式。
-
观察者:监控『被观察者』的行为,一旦发现『被观察者』触发了事件,就会调用事先准备好的方法执行操作。
-
被观察者:『被观察者』一旦触发了被监控的事件,就会被『观察者』发现。
三、ServletContextListener
ServletContextListener是监听ServletContext对象的创建和销毁的,因为ServletContext对象是在服务器启动的时候创建、在服务器关闭的时候销毁,所以ServletContextListener也可以监听服务器的启动和关闭。
将来学习SpringMVC的时候,会用到一个ContextLoaderListener,这个监听器就实现了ServletContextListener接口,表示对ServletContext对象本身的生命周期进行监控。
public class ContextLoaderListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("在服务器启动的时候,模拟创建SpringMVC的核心容器...");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("在服务器启动的时候,模拟销毁SpringMVC的核心容器...");
}
}