一、listener
1.概念
Javaweb中的监听器是用于监听web常见对象HttpServletRequest,HttpSession,ServletContext。
监听web对象的创建与销毁
监听web对象的属性变化
监听session绑定javaBean操作
注意:Listener全部是接口,需要servlet实现对应的接口,对应的类如下:
监听三个对象的创建和销毁
ServletContextListener
ServletRequestListener
HttpSessionListener
监听三个对象属性的变化
ServletContextAttributeListener
ServletRequestAttributeListener
HttpSessionAttributeListener
监听session中javabean的状态
HttpSessionActivationListener(钝化和活化)
HttpSessionBindingListener(绑定和解绑),放在session中就是绑定
2.监听三个对象的创建和销毁
要先配置web.xml
<listener>
<listener-class>it.dragon.listner.myservletcontextlis</listener-class>
</listener>
ServletContextListener
创建:服务器启动的时候,会为每一个项目都创建一个servletContext
销毁:服务器关闭的时候,或者项目被移除的时候
以后用来加载配置文件,在系统启动之后,加载所有配置文件。
ServletRequestListener
创建:整个项目中,有请求来的时候
销毁:整个项目中,有响应生成的时候
HttpSessionListener
创建:java中第一次调用request.getSession的时候、jsp访问的时候创建
销毁:session超时、手动销毁session、服务器非正常关闭
3.监听三个对象属性的变化(添加 替换 删除)
ServletContextAttributeListener
ServletRequestAttributeListener
HttpSessionAttributeListener
监听session中javabean的状态
这两个类需要Javabean实现,而不是servlet。
HttpSessionBindingListener(绑定和解绑),检测java是否添加到session或者从session中移除
session.setAttribute('p',new Person("张三"));
HttpSessionActivationListener(钝化和活化)
钝化:javabean从session中序列化到磁盘上,正常关闭项目时候就会自动序列化
活化:javabean从磁盘上加载到了session中,重新启动时候就可以
注意:类必须实现序列化 serializable
可以通过配置文件修改javabean什么时候钝化,若只对一个项目生效,只需要在项目下/meta-info创建一个context.xml。注意在IDEA中,web项目没有这个文件夹,需要自己创建,否则读取不到context.xml文件。
<Context>
<!--
maxIdleSwap :1分钟 如果session不使用就会序列化到硬盘.
directory :itheima 序列化到硬盘的文件存放的位置.
-->
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="itheima"/>
</Manager>
</Context>
二、filter
Filter是sun公司中servlet2.3后增加的一个新功能。(Servlet规范中三个技术 Servlet Listener Filter)在javaEE中定义了一个接口 javax.servlet.Filter来描述过滤器。通过Filter可以拦截访问web资源的请求与响应操作。WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp,Servlet,静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Filter是一个接口,编写filter步骤:
1.编写一个类
a.实现filter接口,implements Filter
b.重写方法,
2.编写配置文件
a.注册filter
b.绑定路径
3.测试
1.Filter接口的方法
init(FilterConfig config):初始化操作
doFilter(ServletRequest request, ServletResponse response, FilterChain chain):处理业务逻辑
destroy() :销毁操作
2.filter生命周期
filter单实例多线程,filter在服务器启动的时候,服务器创建filter,调用init方法实现初始化操作。请求来的时候,创建一个线程,根据路径调用dofilter执行业务逻辑,当filter被移除的时候或者服务器正常关闭的时候,调用destory方法,执行销毁操作。
3.FilterChain
通过chain的dofilter方法,可以将请求放行到下一个过滤器,直到最后一个过滤器放行才可以访问到servlet或者jsp。
4.url-pattern配置
通过配置url,使得能够匹配到的servlet都将使用该过滤器。
完全匹配 必须以"/" 开始 例如: /a/b
目录匹配 必须以"/" 开始 以"*"结束 例如:/a/b/*
后缀名匹配 以"*."开始 以字符结束 例如 : *.jsp *.do *.action
例如:
afilter 路径 /*
bFilter 路径 /demo4
★一个资源(servlet)有可能被多个过滤器匹配成功,多个过滤器的执行顺序是按照web.xml中filter-mapping的顺序执行。
5.案例1-自动登录
需求:登录的时候,勾选自动登录,登录成功之后,关闭浏览器,下一次访问网站的时候完成登录操作(自动登录)。
autofilter
public class AutoLoginFilter implements Filter{
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
//1.强转
HttpServletRequest request =(HttpServletRequest) req;
HttpServletResponse response =(HttpServletResponse) resp;
//2.完成自动登录
//2.1 判断session中有无登录登录用户 没有的话继续自动登录
User user=(User) request.getSession().getAttribute("user");
if(user==null){
//没有用户 需要自动登录
//2.2 判断访问的资源是否和登录注册相关,若相关则不需要自动登录
String path = request.getRequestURI();// /day1601/xxx
//如果是登录界面,那么显然就不需要进行自动登录了
if(!path.contains("/login")){
//2.3获取指定的cookie
Cookie c = CookUtils.getCookieByName("autologin", request.getCookies());
//判断cookie是否为空
//若不为空 获取值(username和passowrd) 调用serivce完成登录 判断user是否为空 不为空 放入session
if(c!=null){
String username=c.getValue().split("-")[0];
String password=c.getValue().split("-")[1];
//调用serivce完成登录
//user=null;
try {
user = new UserService().login(username, password);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(user!=null){
//将user放入session中
request.getSession().setAttribute("user", user);
}
}
}
}
//3.放行
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
loginservlet
public class Login extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
String usernaeme = req.getParameter("username");
String passwd = req.getParameter("password");
User user = null;
try {
user = new UserService().login(usernaeme,passwd);
} catch (SQLException e) {
e.printStackTrace();
}
if(user==null){
req.setAttribute("msg","can not match username and passed");
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}else{
req.getSession().setAttribute("user",user);
if(Constant.IS_AUTO_LOGIN.equals(req.getParameter("autoLogin"))){
Cookie c = new Cookie("autoLogin",usernaeme+"_"+passwd);
c.setMaxAge(3600);
c.setPath(req.getContextPath()+"/");
resp.addCookie(c);
}
if(Constant.IS_SAVE_NAME.equals(req.getParameter("saveName"))){
//创建cookie
Cookie c=new Cookie("savename", URLEncoder.encode(usernaeme, "utf-8"));
c.setMaxAge(3600);
c.setPath(req.getContextPath()+"/");
resp.addCookie(c);
}
resp.sendRedirect(req.getContextPath()+"/success.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
login.jsp
<body>
<form method="post" action="${pageContext.request.contextPath }/login">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="username" ></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td colspan="1"><input type="checkbox" name="saveName" value="ok">记住用户名</td>
<td colspan="1"><input type="checkbox" name="autoLogin" value="ok">自动登录</td>
</tr>
<tr>
<td colspan="2"><input type="submit"></td>
</tr>
</table>
</form>
<script type="text/javascript">
onload=function(){
var s="${cookie.savename.value }";
s=decodeURI(s);
alert(s);
//将解码后的用户名付给username的文本框
document.getElementsByName("username")[0].value=s;
}
</script>
</body>
</html>
6.filterConfig
过滤器的配置对象,作用:
获取全局管理者
获取当前filter的名称
获取当前filter的初始化参数
7.filter-mapping的子标签
servlet-name
匹配哪个servlet ,就写serlvet标签中servlet-name的值。建议不要在一个filter中重复的匹配servlet。
例如:serlvet的url-pattern:/a/b/hello,serlvet-name:HelloServlet;如果filter中的url-pattern /*,最好不要在写 servlet-name:HelloServlet。
dispatcher匹配哪种请求
默认的是REQUEST,一旦显式的写出来哪种请求,默认就不起作用了。
REQUEST:从浏览器发送过来的请求
FORWARD:转发过来的请求
ERROR:因服务器错误而发送过来的请求,可以自定义好看的界面
INCLUDE:包含过来的请求
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
8.案例2-统一字符编码
需求:开发的时候若有参数,第一步都是设置编码才不会出现乱码。通过过滤器设置,到servlet或者jsp上的时候已经没有乱码问题。
技术分析:
filter 配置路径/* 过滤器的第一个位置,这样可以匹配所有的servlet。
在filter中重写getParameter(加强)
步骤分析:我们只需要在filter中 对request进行加强(例如:只对request.getParameter()进行加强)
方法加强:
1.继承(获取构造器)
2.装饰者模式(静态代理)
3.动态代理
装饰者书写步骤:
1.要求装饰者和被装饰者实现同一个接口或者继承同一个类
2.装饰者中要有被装饰者的引用
3.对需要加强方法进行加强
4.对不需要加强的方法调用原来的方法即可
加强request.getParameter(String key)
首先请求的方式不同,处理的方式也不同
若是get请求
new String(value.getBytes("iso8859-1"),"utf-8");
若是post请求,只需要设置一句话
request.setCharacterEncoding("utf-8");
最后将包装过的request对象(MyRequest)传递给servlet即可
public class EncodingFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
//1.强转
HttpServletRequest request=(HttpServletRequest) req;
HttpServletResponse response=(HttpServletResponse) resp;
//2.放行 将包装过的request传递
chain.doFilter(new MyRequest(request), response);
}
@Override
public void destroy() {
}
}
class MyRequest extends HttpServletRequestWrapper{
private HttpServletRequest request;
public MyRequest(HttpServletRequest request) {
super(request);
this.request=request;
}
@Override
public String getParameter(String name) {
//获取请求方式
String m = request.getMethod();
if("get".equalsIgnoreCase(m)){
//get请求
String value = request.getParameter(name);
try {
return new String(value.getBytes("iso8859-1"),"utf-8");
} catch (UnsupportedEncodingException e) {
}
}else if("post".equalsIgnoreCase(m)){
try {
request.setCharacterEncoding("utf-8");
} catch (UnsupportedEncodingException e) {
}
return request.getParameter(name);
}
return super.getParameter(name);
}
}