java web 之 listen 与 filter
一、Listener监听器
Javaweb开发中的监听器,是用于监听web常见对象 HttpServletRequest HttpSession ServletContext
监听它们的创建与销毁、属性变化 以及session绑定javaBean
1、监听机制
- 事件 就是一个事情
- 事件源 产生这个事情的源头
- 监听器 用于监听指定的事件的对象
- 注册监听 要想让监听器可以监听到事件产生,必须对其进行注册。
2、Javaweb开发中常见监听器
2.1、监听域对象的创建与销毁
- 监听ServletContext创建与销毁 ServletContextListener
- 监听HttpSession创建与销毁 HttpSessionListener
- 监听HttpServletRequest创建与销毁 ServletRequestListener
2.2、监听域对象的属性变化
- 监听ServletContext属性变化 ServletContextAttributeListener
- 监听HttpSession属性变化 HttpSessionAttributeListener
- 监听HttpServletRequest属性变化 ServletRequestAttributeListener
2.3、监听session绑定javaBean
它是用于监听javaBean对象是否绑定到了session域 HttpSessionBindingListener
它是用于监听javaBean对象的活化与钝化 HttpSessionActivationListener
3、监听器的快速入门
关于创建一个监听器的步骤
- 创建一个类,实现指定的监听器接口
- 重写接口中的方法
- 在web.xml文件中对监听器进行注册。
- ServletContext对象的创建与销毁
3.1、关于域对象创建与销毁的演示
这个对象是在服务器启动时创建的,在服务器关闭时销毁的。
HttpSession对象的创建与销毁
HttpSession session=request.getSession();
Session销毁 的方法
- 默认超时 30分钟
- 关闭服务器
- invalidate()方法
- setMaxInactiveInterval(int interval) 可以设置超时时间
问题:直接访问一个jsp页面时,是否会创建session?
会创建,因为我们默认情况下是可以在jsp页面中直接使用session内置对象的。
HttpServletRequest创建与销毁
Request对象是发送请求服务器就会创建它,当响应产生时,request对象就会销毁。
3.2、演示了Request域对象中属性变化
在java的监听机制中,它的监听器中的方法都是有参数的,参数就是事件对象,而我们可以通过事件对象直接获取事件源。
3.3、演示session绑定javaBean
1、javaBean对象自动感知被绑定到session中.
HttpSessionBindingListener 这个接口是由javaBean实现的,并且不需要在web.xml文件中注册.
2、javabean对象可以活化或钝化到session中。
HttpSessionActivationListener如果javaBean实现了这个接口,那么当我们正常关闭服务器时,session中的javaBean对象就会被钝化到我们指定的文件中。
当下一次在启动服务器,因为我们已经将对象写入到文件中,这时就会自动将javaBean对象活化到session中。
我们还需要个context.xml文件来配置钝化时存储的文件
在meta-inf目录下创建一个context.xml文件
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="it315"/>
</Manager>
</Context>
案例-定时销毁session
1、怎样可以将每一个创建的session全都保存起来?
我们可以做一个HttpSessionListener,当session对象创建时,就将这个session对象装入到一个集合中.
将集合List<HttpSession>保存到ServletContext域中。
2、怎样可以判断session过期了?
在HttpSession中有一个方法public long getLastAccessedTime()
它可以得到session对象最后使用的时间,可以使用invalidate方法销毁。
ps(我们上面的操作需要使用任务调度功能.)在java中有一个Timer定时器类
package com.timer; import java.util.Date;
import java.util.Timer;
import java.util.TimerTask; public class TestTimer {
public static void main(String[] args) {
Timer t = new Timer(); t.schedule(new TimerTask() { @Override
public void run() {
System.out.println(new Date().toLocaleString());
}
}, 2000, 1000);
}
}
关于三个域对象获取
如果在Servlet中要获取request,在方法上就有,request.getSession() getServletContext();
如果我们有request对象了, request.getSession() request.getSession().getServletCotnext();
public class MySessionListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent arg0) {
HttpSession session = arg0.getSession();
//得到application中的list集合
ServletContext application = session.getServletContext();
//得到session对象,并放入list集合
List<HttpSession> list =(List<HttpSession>) application.getAttribute("sessions");
list.add(session);
System.out.println("添加了"+session.getId());
}
public void sessionDestroyed(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
} }
程序在使用时,需要考虑并发问题,因为我们在web中,它一定是一个多线程的,那么我们的程序对集合进行了添加,还有移除操作。具体在MyServletContextListener的方法中如下
public class MyServletContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
}
public void contextInitialized(ServletContextEvent arg0) {
//通過事件原對象得到事件源
ServletContext application = arg0.getServletContext();
//创建一个集合 存储所有session对象
final List<HttpSession> list = Collections.synchronizedList(new ArrayList<HttpSession>());
application.setAttribute("sessions", list);
//创建一个计时器对象
Timer t = new Timer();
t.schedule(new TimerTask() { @Override
public void run() {
System.out.println("开始扫描");
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
HttpSession session = (HttpSession) iterator.next();
long l = System.currentTimeMillis() - session.getLastAccessedTime();
if(l > 5000){
System.out.println("session移除了"+session.getId());
session.invalidate();
iterator.remove();
}
}
}
}, 2000, 5000);
}
}
二、Filter
二、Filter过滤器(重要)
Javaweb中的过滤器可以拦截所有访问web资源的请求或响应操作。
1.1、步骤:
- 创建一个类实现Filter接口
- 重写接口中方法 doFilter方法是真正过滤的。
- 在web.xml文件中配置
注意:在Filter的doFilter方法内如果没有执行chain.doFilter(request,response),那么资源是不会被访问到的。
1.2、FilterChain
FilterChain 是 servlet 容器为开发人员提供的对象,它提供了对某一资源的已过滤请求调用链的视图。过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。
问题:怎样可以形成一个Filter链?
只要多个Filter对同一个资源进行拦截就可以形成Filter链
问题:怎样确定Filter的执行顺序?
由<filter-mapping>来确定
1.3、Filter生命周期
Servlet生命周期:
实例化 --》 初始化 --》 服务 --》 销毁
- 1 当服务器启动,会创建Filter对象,并调用init方法,只调用一次.
- 2 当访问资源时,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,这个方法是真正拦截操作的方法.
- 3 当服务器关闭时,会调用Filter的destroy方法来进行销毁操作.
1.4、FilterConfig
在Filter的init方法上有一个参数,类型就是FilterConfig.
FilterConfig它是Filter的配置对象,它可以完成下列功能
- 获取Filtr名称
- 获取Filter初始化参数
- 获取ServletContext对象。
问题:怎样在Filter中获取一个FIlterConfig对象?
package com.itheima.filter; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class MyFilterConfigTest implements Filter{ private FilterConfig filterConfig; public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
} public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//通过FilterConfig对象获取到配置文件中的初始化信息
String encoding = filterConfig.getInitParameter("encoding");
System.out.println(encoding);
request.setCharacterEncoding(encoding);
//放行
chain.doFilter(request, response);
} public void destroy() {
// TODO Auto-generated method stub
}
} 如下 web.xml配置
<filter>
<filter-name>MyFilterConfigTest</filter-name>
<filter-class>com.itheima.filter.MyFilterConfigTest</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter> <filter-mapping>
<filter-name>MyFilterConfigTest</filter-name>
<servlet-name>ServletDemo2</servlet-name>
</filter-mapping>
1.5、Filter配置
基本配置
<filter>
<filter-name>filter名称</filter-name>
<filter-class>Filter类的包名.类名</filter-class>
</filter>
<filter-mapping>
<filter-name>filter名称</filter-name>
<url-pattern>路径</url-pattern>
</filter-mapping>
关于其它配置
1.<url-pattern>
完全匹配 以”/demo1”开始,不包含通配符*
目录匹配 以”/”开始 以*结束
扩展名匹配 *.xxx 不能写成/*.xxx
2.<servlet-name>
它是对指定的servlet名称的servlet进行拦截的。
3.<dispatcher>
可以取的值有 REQUEST FORWARD ERROR INCLUDE 根据跳转方式拦截
它的作用是:当以什么方式去访问web资源时,进行拦截操作.
1.REQUEST 当是从浏览器直接访问资源,或是重定向到某个资源时进行拦截方式配置的 它也是默认值
2.FORWARD 它描述的是请求转发的拦截方式配置
3.ERROR 如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
4.INCLUDE 如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用
三、自动登录 (PS bean的属性名和数据库里的字段名千万要一样哦 不然会emmm 很惨)
- 当用户登陆成功后,判断是否勾选了自动登陆,如果勾选了,就将用户名与密码持久化存储到cookie
- 做一个Filter,对需要自动登陆的资源进行拦截
首写要在登录Servlet中登录成功时把登录的信息保存在cookie里,并设置存活时间
if(null != user){
String autologin = request.getParameter("autologin"); Cookie cookie = new Cookie("user", user.getUsername()+"&"+user.getPassword());
cookie.setPath("/");
if(autologin != null){// on / null
cookie.setMaxAge(60*60*24*7);
}else{
cookie.setMaxAge(0);
}
response.addCookie(cookie);
request.getSession().setAttribute("user", user);
request.getRequestDispatcher("/home.jsp").forward(request, response);
}
然后设置好filter类 记住要在web.xml里面配置 如下 为 doFilter代码
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
//1、转换对象
HttpServletRequest req = (HttpServletRequest) arg0;
String uri = req.getRequestURI();
String path = req.getContextPath();
path = uri.substring(path.length()); if(!("/login.jsp".equals(path)||"/servlet/loginServlet".equals(path))){ User user = (User) req.getSession().getAttribute("user");
if(user == null){
//2、处理业务
Cookie[] cookies = req.getCookies();
String username = "";
String password = "";
for (int i = 0;cookies!=null && i < cookies.length; i++) {
if("user".equals(cookies[i].getName())){
String value = cookies[i].getValue();
String[] values = value.split("&");
username = values[0];
password = values[1];
}
}
UserService us = new UserService();
User u = us.findUser(username, password);
if(u != null){
req.getSession().setAttribute("user", u);
}
}
}
//3、放行
arg2.doFilter(arg0, arg1);
}
ps 当访问别的页面时通过判断session时减少访问数据库的操作
四、MD5加密
在mysql中可以对数据进行md5加密 Md5(字段)
UPDATE USER SET PASSWORD=MD5(PASSWORD);
需要一个MD5Utils工具类
package com.util; import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; public class MD5Utils {
/**
* 使用md5的算法进行加密
*/
public static String md5(String plainText) {
byte[] secretBytes = null;
try {
secretBytes = MessageDigest.getInstance("md5").digest(
plainText.getBytes());
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("没有md5这个算法!");
}
String md5code = new BigInteger(1, secretBytes).toString(16);
for (int i = 0; i < 32 - md5code.length(); i++) {
md5code = "0" + md5code;
}
return md5code;
}
}
这样在loginservlet调用一下方法转化一下就ok了。
五、全局的编码过滤器
之前做的操作,只能对post请求是ok
怎样可以做成一个通用的,可以处理post,get所有的请求的?
在java中怎样可以对一个方法进行功能增强?
- 继承
- 装饰设
- 创建一个类让它与被装饰类实现同一个接口或继承同一个父类
- 在装饰类中持有一个被装饰类的引用
- 重写要增强的方法
我们可以用getparameterMap这个方法来实现getparameter和getparametervalues两个方法 即MyFilter 最终版本
package com.filter; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; public class MyFilter implements Filter{ public void destroy() {
// TODO Auto-generated method stub } public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) arg0;
req = new MyRequest(req);
arg2.doFilter(req, arg1); } public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub } }
class MyRequest extends HttpServletRequestWrapper{ private HttpServletRequest request; public MyRequest(HttpServletRequest request) {
super(request);
this.request = request;
} /*@Override
public String getParameter(String name) {
name = request.getParameter(name);
try {
return new String(name.getBytes("iso-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}*/
@Override
public String getParameter(String name) {
Map<String, String[]> map = getParameterMap();
return map.get(name)[0];
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> map = getParameterMap();
return map.get(name);
}
private boolean flag = true; //防止重复
public Map<String, String[]> getParameterMap() {
Map<String, String[]> map = request.getParameterMap();
if(flag){
for (Map.Entry<String, String[]> m : map.entrySet()) {
String[] values = m.getValue();
for (int i = 0; i < values.length; i++) {
try {
values[i] = new String(values[i].getBytes("iso-8859-1"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
flag =false;
}
return map;
}
}
java web 之 listen 与 filter的更多相关文章
- java web基础 --- URL重定向Filter
java web基础 --- URL重定向Filter httpRequest.getRequestDispatcher("/helloWorld").forward(httpRe ...
- Java Web之过滤器(Filter)
转: Java Web之过滤器(Filter) 2018年07月31日 16:58:40 喻志强 阅读数 13705更多 所属专栏: Java Web入门 版权声明:本文为博主原创文章, 转载请注 ...
- Java Web组件Servlet、Filter、Listener
一.Servlet 类javax.servlet.http.HttpServlet; 1.是单例模式,一个web容器中只有一个实例.服务器调用它的service方法进行请求处理, service方法又 ...
- Java web中listener、 filter、servlet 加载顺序
真正的加载顺序为:context-param -> listener -> filter -> servlet 加载顺序与它们在 web.xml 文件中的先后顺序无关.即不会因为 f ...
- Java Web学习(十一)Java过滤器
一.引言 上一篇文章学习了java三大器的拦截器,拦截器主要是针对于action请求进行拦截处理的,那么对于requst的一些信息如果在调用前,想先进行过滤和处理,那么就要使用到第二个神器,也就是本文 ...
- java web filter 学习(2)
本文主要对filter的基本使用进行了讲解,其中涉及到了 filter是什么 一个filter处理一个jsp 多个filter处理一个jsp filter是什么 Filter 是java下的一种过滤器 ...
- Java web学习filter (1)
一.概念:Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源: 例如Jsp, Servlet, 静态图片文件 ...
- Java Web之Filter
Filter被称为过滤器或者拦截器,基本功能就是对调用servler过程的拦截,在servlet进行响应和处理前后实现一些特殊功能.其实,Filter过滤器就是一个实现了javax.servlet.F ...
- Java Web进阶——Filter过滤器
一.过滤器的介绍: 在Servlet规范2.3中定义了过滤器,它是一个服务器端的组件,可以截取用户端的请求与响应信息,并且对这些信息进行过滤. Servlet过滤器本身并不生成请求和响应对象,只是提供 ...
随机推荐
- C++技术问题总结-第8篇 STL内存池是怎么实现的
STL内存池机制,使用双层级配置器.第一级採用malloc.free,第二级视情况採用不同策略. 这样的机制从heap中要空间,能够解决内存碎片问题. 1.内存申请流程图 简要流程图例如以下. ...
- Mybatis+Oracle批处理
1. 批处理 插入 非常多时候都涉及到一系列数据的插入,通过mybatis的动态sql语句可以非常好的解决问题.当然.oracle已经提供了批插入的语句: insert into students s ...
- xml基本语法(2)
本节要点: 了解XML的文档声明 了解XML的元素.命名规则.属性.元素内容.处理指令等概念 1 XML文档声明 表示该文档是一个XML文档,以及遵循哪个XML版本的规范. 规范:<?xml 版 ...
- ASP.NET Core 指定环境发布(hosting environment)
ASP.NET Core 应用程序发布命令: dotnet publish [<PROJECT>] [-f|--framework] [-r|--runtime] [-o|--output ...
- Java加密与解密笔记(三) 非对称加密
非对称的特点是加密和解密时使用的是不同的钥匙.密钥分为公钥和私钥,用公钥加密的数据只能用私钥进行解密,反之亦然. 另外,密钥还可以用于数字签名.数字签名跟上文说的消息摘要是一个道理,通过一定方法对数据 ...
- springMVC上传错误StandardMultipartHttpServletRequest
异常信息 java.lang.ClassCastException: org.springframework.security.web.servletapi.HttpServlet3RequestFa ...
- Html转JSP样式变型问题解决
一.问题描述 在我没将写好的 html 页面转变为 java web 中的 JSP 页面时.有时会发现,我们将 css .js 都引入到了页面中.当样式和我们想象的不一样,那么我们就要去解决这个问题. ...
- Asp.Net Web API中使用Session,Cache和Application的几个方法
在ASP.NET中,Web Api的控制器类派生于ApiController,该类与ASP.NET的Control类没有直接关系,因此不能像在Web MVC中直接使用HttpContext,Cache ...
- web项目错误页面友好处理404,500等
写在前面: 在web项目中,可能会出现404.500等错误页面,给用户体验不怎么好,所以我们可以对这些错误页面进行友好的处理. 步骤: 1.配置web.xml: <!-- 错误页面友好显示 -- ...
- 聊天机器人(基于android)
1.本人最近写了一个小项目关于语音聊天的,采用讯飞语音引擎和数据,看看效果 2.项目名称叫小秘书,它可以和你进行交互,可以通过语音聊天,蛮有意思的,聊天内容你也可以定制 3.如果想做这款应用,先看看我 ...