Filter:
主要是对用户请求的预处理,和对相应后的处理Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成相应,最后Filter在对服务器相应做出处理。
它的几项用处:
--在HttpServletRequest到达Servlet之前,拦截客户端的HttpServletRequest
--根据需要检查HttpServletRequest,也可以更改HttpServletRequest的头和数据
--在HttpServletRespone到达客户端之前,拦截HttpServletRespone
--根据需要检查HttpServletRespone,也可以更改HttpServletRespone的头和数据
File有以下几类:
用户授权的File:负责检查用户请求,根据请求过滤掉用户的非法请求
日志:详细记录某些特殊用户的请求
负责解码:包括非标准编码的请求
改变XML的XSLT Filter
一个File可以拦截多个请求,一个请求也可以被多个请求拦截
创建Filter只需两步:
创建Filter处理类
在Web.xml文件中配置Filter或在Filter类中进行注解
创建Filter:
创建Filter必须实现javax.servlet.Filter接口,该接口定义了一下三个方法。
Void init(FilterConfig config):用于完成Filter的初始化
Void destroy():用于Filter销毁前,完成某些资源回收
Void doFile(ServlterRequest request,ServlterReponse reponse, FilterChain chain):实现过滤功能,该方法就是对每个请求及其响应增加额外的处理。
package logFiler;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class log implements Filter {
private FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
config=filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletContext servletContext = this.config.getServletContext();
HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
System.out.println("开始过滤...");
String servletPath = httpServletRequest.getServletPath();
long l = System.currentTimeMillis();
System.out.println("用户请求的路径为:"+servletPath);
filterChain.doFilter(servletRequest,servletResponse);
long l1 = System.currentTimeMillis();
System.out.println("响应用户的路径为:"+httpServletRequest.getRequestURI()+"耗时"+(l1-l));
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
Filter与Servlet非常相似,他们具有完全相同的生命周期,也可以通过Web.xml和@WebFilter写入配置和参数,在Filter中获取初始化参数使用FilterConfig()或getInitParament()方法,下面我们来写一段较为使用的代码:
package logFiler;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class Autor implements Filter {
private FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
config=filterConfig;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
httpServletRequest.setCharacterEncoding("GBK");
HttpSession session = httpServletRequest.getSession(true);
String servletPath = httpServletRequest.getServletPath();
//如果在session范围的用户名为空表明而且用户请求页面不在登录或是注册页面,说明用户并没有登录就去请求其他信息
if (session.getAttribute("user")==null
&& !servletPath.endsWith("login.jsp")
&& !servletPath.endsWith("logon.jsp")
){
servletRequest.setAttribute("tip","你还没有登录!");
servletRequest.getRequestDispatcher("logon.jsp").forward(servletRequest,servletResponse);
}//否则就放行
else {
filterChain.doFilter(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
config=null;
}
}
使用URL Rewrite实现网站伪静态
大部分的搜索引擎多会优先收录静态的html,而不是像jsp、php之类的动态页面,而大部分互联网上的网站多是动态的,这时我们就需要将动态网站进行处理变为伪静态
关于Listener:
在Web应用中会发生各种事件,比如说应用的启动与暂停,用户会话的开始与结束,请求的到达,域参数发生改变....
Servlet API为我们提供了可供监控这些事件的接口Listener,实现这些接口有以下两个步骤:
- 实现Listener接口
- 在Web.xml或注解中配置
我们先来介绍一下Listener接口的配置
@1.第一种在创建监听器类时在使用注释@WebListener
@2.第二种在创建web.xml中使用
常用的Web事件监听接口有如下几个:
ServletContextListener: 用于监听Web应用的启用与销毁
ServletContextAttributeListener:用于监听ServletContext范围(application)内属性的改变
ServletRequestListener:用于监听用户的请求
ServletRequestAttributeListener:用于监听request范围内的属性改变
HttpSessionListener:用于监听用户会话的开始与结束
HttpSessionAttributeListener:用于监听用户session范围内的属性的变化
我们将一一介绍这几个接口和他们的方法:
- ServletContextListener,该接口包含有以下两个方法:
contextInitialized(ServletContextEvent sce):Web应用程序开启的时候会调用该方法
ContextDestroyed(ServletContextEvent sce):Web应用程序销毁的时候调用该方法
以上可以通过事件参数ServletContext的getServletContext()方法来获取应用的上下文servletContext的实例也就是application
2.ServletContextAttributeListener,该接口包含了一下三个接口:
-
- attributeAdded(ServletContextAttributeEvent event):程序向ServletContext(application)的范围添加属性的时候调用该方法
- attributeRemoved(ServletContextAttributeEvent event):程序将一个属性从application的范围内移除的时候调用该方法
- attributeReplaced(ServletContextAttributeEven even):程序将application中的一个属性替换就调用该方法
以上通过事件参数ServletContextAttributeEven类的
getServletContext()方法来获取应用程序的上下文,通过getName()和getValue()方法可以获得改变的属性名称与值
3.ServletRequestListener:需要实现以下两个方法:
RequestInitalized(ServletRequestEven sre):用户请求到达时调用
RequestDestroyed:用户请求销毁的时候调用
- ServletRequestAttributeListener:需要实现以下三个方法:
attributeAdded(ServletRequestEvent src):在ServletRequest(request)范围内的属性被添加时调用该方法
attributeRemoved(ServletRequestEvent src):在ServletRequest(request)范围内的属性被移除时调用该方法
attributeReplaced(ServletRequestEvent src):在ServletRequest(request)范围内的属性被替换时调用该方法
通过以上方法的参数的getName()与getValue()方法来获取对应变化的属性名与属性值,
以上的监听器可用来监听用户的每一个请求,从而实现系统日志
- HttpSessionListener:实现以下两个方法:
sessionCreated(HttpSessionEvent se):用户与服务器会话开始、创建时调用
sessionDestroyed(HttpSessionEvent se):用户与服务器的会话断开、销毁时触发该方法
package Listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.sql.Connection;
import java.util.*;
public class fourListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession Session = se.getSession(); //获取当前会话的对象
ServletContext servletContext = Session.getServletContext(); //通过会话对象来获取到ServletContext也就是(application)域
String id = Session.getId(); //获取当前会话的ID
if (Session.isNew()){ //判断该会话是否为第一次
String name = (String)Session.getAttribute("name"); //通过会话域来获取用户名
name=name==null?"游客":name; //判断用户名是否为空,为空就是以游客身份访问
Map online= (Map) servletContext.getAttribute("online"); //获取在ServletContext的属性online将其转化为Map类型
if (online==null){ //如果当前这个属性为空就去创建该属性 这个属性是一个包含会话ID与用户名的Map结构的对象,以ID为键,用户名为值
online= Collections.synchronizedMap(new HashMap());
}
online.put(id,name);
servletContext.setAttribute("online",online); //将该变量放进应用程序范围内 在其他地方若是想看用户的ID和用户名可以查询这里
}
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession seSession = se.getSession();
String id = seSession.getId();
ServletContext servletContext = seSession.getServletContext();
Map online=(Map) servletContext.getAttribute("online");
if (online!=null){
online.remove(id);
}
servletContext.setAttribute("online",online);
}
}
jsp代码:
<%@ page import="java.util.Map" %>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
JSP - Hello World
<%
Map online=(Map) application.getAttribute("online");
String id = session.getId();
String name = online.get(id);
%>
<%=id%> <%=name%>
- HttpSessionAttributeListener:实现以下三个方法:
attributeAdded(ServletSessionEvent src):在HttpSession(session)范围内的属性被添加时调用该方法
attributeRemoved(ServletSessionEvent src):在HttpSession(session)范围内的属性被移除时调用该方法
attributeReplaced(ServletSessionEvent src):在HttpSession(session)范围内的属性被替换时调用该方法
采用HttpSessionListener监听用户在线信息比较少只能获取用户会话id,用户名,多少人在线等基本消息,而我们采用HttpServletRequest来实现可以获取到用户停留在某一个页面、本次停留时间、用户访问的ip等,
package test;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
public class RequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest servletRequest = (HttpServletRequest)sre.getServletRequest();
HttpSession session = servletRequest.getSession(true); //通过HttpServletRequest的getSession()方法来获取会话
String path = servletRequest.getRequestURI();
String id = session.getId();
String ip = servletRequest.getRemoteAddr();
String name =(String) session.getAttribute("name");
name=name==null?"游客":name;
connection connection = new connection();
Connection connectiondata = null;
ResultSet execute = null;
try {
String sql="SELECT * FROM userinfo WHERe SessionID=?"; //查询未知的SessionID的所有数据
connectiondata = connection.connectiondata();
execute = connection.execute(connectiondata, sql);
if (execute.next()){ //如果上面查询结果有值就证明该用户已经不是会话开始
execute.updateString("path",path);
execute.updateString("time", String.valueOf(System.currentTimeMillis()));
execute.rowUpdated(); //以上代码时为了同步当前用户访问的页面与访问时间,同步到数据库当中
execute.close();
}else {
connection.Insert(id,name,ip,path, execute.getCursorName()); //证明用户刚进入会话,将用户信息插入到数据库表中
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void requestDestroyed(ServletRequestEvent sre) {
}
}
package test;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import test.GetRunner;
@WebServlet(urlPatterns = "/Asyn",asyncSupported = true)
public class Asyn extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=GBK");
PrintWriter out = resp.getWriter();
out.println("异步调用实例 ");
out.println("进入Servlet时间为:"+new java.util.Date()+".
");
//创建一个AsyncContext对象,开始异步调用
AsyncContext asyncContext = req.startAsync();
//设置异步调用的超时时长
asyncContext.setTimeout(60*1000);
//启动异步调用的线程
asyncContext.start(new GetRunner(asyncContext));
out.println("结束Servlet的时间:"+new java.util.Date()+".
");
}
}
package test;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import test.GetRunner;
@WebServlet(urlPatterns = "/Asyn",asyncSupported = true)
public class Asyn extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=GBK");
PrintWriter out = resp.getWriter();
out.println("异步调用实例 ");
out.println("进入Servlet时间为:"+new java.util.Date()+".
");
//创建一个AsyncContext对象,开始异步调用
AsyncContext asyncContext = req.startAsync();
//设置异步调用的超时时长
asyncContext.setTimeout(60*1000);
//启动异步调用的线程
asyncContext.start(new GetRunner(asyncContext));
out.println("结束Servlet的时间:"+new java.util.Date()+".
");
}
}



