目录
1.过滤器
2.监听器
1.过滤器
对所有资源请求进行拦截
权限访问控制、过滤敏感词汇、压缩响应信息
web应用程序启动时,服务器会创建Filter的实例对象,并调用其init方法。
服务器每次调用web资源的service方法之前,会先调用一下filter的doFilter方法
多个Filter组合起来称之为一个Filter链,按web.xml中顺序,决定先调用哪个Filter
步骤
1.implements Filter
2.web.xml配置
Filter处理类---统一设置编码
package com.sst.cx;
import java.io.IOException;
import java.util.Enumeration;
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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet Filter implementation class TestFilter
*/
@WebFilter("/TestFilter")
public class TestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("----过滤器初始化----");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//对request和response进行一些预处理
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("前!!!");
chain.doFilter(request, response); //让目标资源执行,放行
System.out.println("后!!!");
}
@Override
public void destroy() {
System.out.println("----过滤器销毁----");
}
}
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.sst.cx.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
Filter处理类---统一设置编码(带有初始化参数的过滤器)
package com.sst.cx;
import java.io.IOException;
import java.util.Enumeration;
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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet Filter implementation class TestFilter
*/
@WebFilter("/TestFilter")
public class TestFilter implements Filter {
private FilterConfig filterConfig = null;
// 设置默认的字符编码
private String defaultCharset = "UTF-8";
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("----过滤器初始化----");
this.filterConfig = filterConfig;
// 获取 过滤器名
String filterName = filterConfig.getFilterName();
// 获取 在web.xml文件中配置的初始化参数
String initParam1 = filterConfig.getInitParameter("name");
String initParam2 = filterConfig.getInitParameter("like");
// 获取 在web.xml文件中配置的初始化参数集合。
Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String paramName = (String) initParameterNames.nextElement();
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// 得到在web.xml中配置的字符编码
String charset = filterConfig.getInitParameter("charset");
if(charset==null){
charset = defaultCharset;
}
req.setCharacterEncoding(charset);
resp.setCharacterEncoding(charset);
resp.setContentType("text/html;charset="+charset);
MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(req);
chain.doFilter(requestWrapper, resp);
}
@Override
public void destroy() {
System.out.println("----过滤器销毁----");
}
}
/**
* @ClassName: MyCharacterEncodingRequest
* @Description: Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,
* (HttpServletRequestWrapper类实现了request接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 request对象的对应方法)
* 以避免用户在对request对象进行增强时需要实现request接口中的所有方法。
* 所以当需要增强request对象时,只需要写一个类继承HttpServletRequestWrapper类,然后在重写需要增强的方法即可
* 1.实现与被增强对象相同的接口
2、定义一个变量记住被增强对象
3、定义一个构造函数,接收被增强对象
4、覆盖需要增强的方法
5、对于不想增强的方法,直接调用被增强对象(目标对象)的方法
*/
class MyCharacterEncodingRequest extends HttpServletRequestWrapper{
//定义一个变量记住被增强对象(request对象是需要被增强的对象)
private HttpServletRequest request;
//定义一个构造函数,接收被增强对象
public MyCharacterEncodingRequest(HttpServletRequest request) {
super(request);
this.request = request;
}
/* 覆盖需要增强的getParameter方法
* @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
*/
@Override
public String getParameter(String name) {
try{
//获取参数的值
String value= this.request.getParameter(name);
if(value==null){
return null;
}
//如果不是以get方式提交数据的,就直接返回获取到的值
if(!this.request.getMethod().equalsIgnoreCase("get")) {
return value;
}else{
//如果是以get方式提交数据的,就对获取到的值进行转码处理
value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
return value;
}
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>com.sst.cx.TestFilter</filter-class>
<init-param>
<description>配置过滤器的初始化参数1</description>
<param-name>name</param-name>
<param-value>hello</param-value>
</init-param>
<init-param>
<description>配置过滤器的初始化参数2</description>
<param-name>like</param-name>
<param-value>java</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
过滤器进阶
装饰模式又名包装(Wrapper)模式
在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。
当某个对象的方法不适应业务需求时,通常有2种方式可以对方法:
1.编写子类,覆盖需增强的方法。
2.使用Decorator设计模式对方法进行增强。(无法得到class文件时)
实现步骤
1.编写一个类去继承被增强对象所继承的接口或父类。
2.在类中定义一个变量(变量类型即需增强对象的类型)。
3.在类中定义一个构造函数(接收需增强的对象)。
4.覆盖需增强的方法。
Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper 类实现了request 接口中的所有方法
未完待续。。。
2.监听器
一个用来监听其他对象方法或属性改变的普通类(触发后调用指定方法)
事件监听涉及到三个组件:事件源、事件对象、事件监听器
当事件源上发生某一个动作时,它会调用事件监听器的某个方法(传入事件对象,通过事件对象,就可以拿到事件源)
监听器(处理java类)
例1
package com.sst.cx;
import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class TestListener {
public static void main(String[] args) {
Frame f = new Frame();
f.setSize(400, 400);
f.setVisible(true);
// 添加监听(注册事件监听器)
f.addWindowListener(new WindowListener(){
// 窗体处于活跃状态时调用
public void windowActivated(WindowEvent e) {
System.out.println("处于活跃状态");
}
// 窗体已经关闭后调用
public void windowClosed(WindowEvent e) {
System.out.println("窗体已经关闭");
}
// 正在关闭时调用
public void windowClosing(WindowEvent e) {
// 通过事件对象e来获取事件源对象
Frame f = (Frame) e.getSource();
System.out.println(f+"窗体正在关闭");
f.dispose();
}
// 处于非活跃状态时调用
public void windowDeactivated(WindowEvent e) {
System.out.println("处于非活跃状态");
}
public void windowDeiconified(WindowEvent e) {
System.out.println("?");
}
public void windowIconified(WindowEvent e) {
System.out.println("?");
}
public void windowOpened(WindowEvent e) {
System.out.println("窗体打开后调用");
}
});
}
}
例2
package com.sst.cx;
import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class TestListener {
public static void main(String[] args) {
//
Person p = new Person();
//注册监听p对象行为的监听器
p.registerListener(new PersonListener() {
//监听p吃东西这个行为
public void doeat(Event e) {
Person p = e.getSource();
System.out.println(p + "在吃东西");
}
//监听p跑步这个行为
public void dorun(Event e) {
Person p = e.getSource();
System.out.println(p + "在跑步");
}
});
//p在吃东西
p.eat();
//p在跑步
p.run();
}
}
/**
* @ClassName: Person(事件源)
* @Description: 设计一个Person类作为事件源,这个类的对象的行为(比如吃饭、跑步)可以被其他的对象监听
*
*/
public class Person {
/**
* @Field: listener
* 在Person类中定义一个PersonListener变量来记住传递进来的监听器
*/
private PersonListener listener;
/**
* @Method: eat
* @Description: 设计Person的行为:吃
*
*/
public void eat() {
if (listener != null) {
/**
* 调用监听器的doeat方法监听Person类对象eat(吃)这个动作,将事件对象Event传递给doeat方法,
* 事件对象封装了事件源,new Event(this)中的this代表的就是事件源
*/
listener.doeat(new Event(this));
}
}
/**
* @Method: run
* @Description: 设计Person的行为:跑
*
*/
public void run() {
if (listener != null) {
/**
* 调用监听器的dorun方法监听Person类对象run(跑)这个动作,将事件对象Event传递给doeat方法,
* 事件对象封装了事件源,new Event(this)中的this代表的就是事件源
*/
listener.dorun(new Event(this));
}
}
/**
* @Method: registerListener
* @Description: 这个方法是用来注册对Person类对象的行为进行监听的监听器
*
* @param listener
*/
public void registerListener(PersonListener listener) {
this.listener = listener;
}
}
/**
* @ClassName: PersonListener(事件监听器)
* @Description: 设计Person类(事件源)的监听器接口
*
*/
interface PersonListener {
/**
* @Method: doeat
* @Description: 这个方法是用来监听Person对象eat(吃)这个行为动作,
* 当实现类实现doeat方法时就可以监听到Person类对象eat(吃)这个动作
*
* @param e
*/
void doeat(Event e);
/**
* @Method: dorun
* @Description: 这个方法是用来监听Person对象run(跑)这个行为动作,
* 当实现类实现dorun方法时就可以监听到Person类对象run(跑)这个动作
*
* @param e
*/
void dorun(Event e);
}
/**
* @ClassName: Event(事件对象)
* @Description:设计事件类,用来封装事件源
*
*/
class Event {
/**
* @Field: source
* 事件源(Person就是事件源)
*/
private Person source;
public Event() {
}
public Event(Person source) {
this.source = source;
}
public Person getSource() {
return source;
}
public void setSource(Person source) {
this.source = source;
}
}
JavaWeb中的监听器
用于
1.监听域对象(ServletContext, HttpSession和 ServletRequest)自身的创建和销毁的事件监听器。
2.监听域对象中的属性的增加和删除的事件监听器。
3.监听绑定到HttpSession域中的某个对象的状态的事件监听器。
监听ServletContext对象的创建和销毁事件
ServletContextListener接口
创建:服务器启动后创建ServletContext(针对每一个Web应用)
销毁:服务器关闭前关闭ServletContext(代表每一个web应用)
步骤:
1.implements ServletContextListener
2.web.xml
监听类
package com.sst.cx;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
* Application Lifecycle Listener implementation class MyServletContextListener
*
*/
@WebListener
public class MyServletContextListener implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent arg0) {
// TODO Auto-generated method stub
System.out.println("ServletContext--对象销毁");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
// TODO Auto-generated method stub
System.out.println("ServletContext--对象创建");
}
}
web.xml中+
<!-- 注册针对ServletContext对象进行监听的监听器 -->
<listener>
<description>ServletContextListener监听器</description>
<!--实现了ServletContextListener接口的监听器类 -->
<listener-class>com.sst.cx.MyServletContextListener</listener-class>
</listener>
监听HttpSession域对象的创建和销毁
HttpSessionListener接口
创建一个Session时,激发sessionCreated (HttpSessionEvent se) 方法
销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se) 方法。
监听类
package com.sst.cx;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* Application Lifecycle Listener implementation class MyHttpSessionListener
*
*/
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println( se.getSession() + "=====创建了!!");
}
/* HttpSession的销毁时机需要在web.xml中进行配置,如下:
* <session-config>
<session-timeout>1</session-timeout>
</session-config>
这样配置就表示session在1分钟之后就被销毁
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session销毁了!!");
}
}
web.xml 同上
jsp
触发:
${pageContext.session.id}
监听ServletRequest域对象的创建和销毁
ServletRequestListener接口
Request对象被创建(用户每一次访问都会创建request对象)时,调用监听器的requestInitialized(ServletRequestEvent sre)方法
Request对象被销毁(当前访问结束,request对象就会销毁)时,调用监听器的requestDestroyed(ServletRequestEvent sre)方法
监听类
package com.sst.cx;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
/**
* Application Lifecycle Listener implementation class MyServletRequestListener
*
*/
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println(sre.getServletRequest() + "销毁了!!");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println(sre.getServletRequest() + "创建了!!");
}
}
web.xml 同上
jsp
触发:
<%--使用c:url标签构建url,构建好的url存储在servletDemo1变量中--%>
<c:url value="/servlet/ServletDemo1" scope="page" var="servletDemo1">
<%--构建的url的附带的中文参数 ,参数名是:username,值是:孤傲苍狼--%>
<c:param name="username" value="孤傲苍狼"></c:param>
</c:url>
<%--使用get的方式访问 --%>
<a href="${servletDemo1}">超链接(get方式请求)</a>
<hr/>
<%--使用post方式提交表单 --%>
<form action="${pageContext.request.contextPath}/servlet/ServletDemo1" method="post">
用户名:<input type="text" name="username" value="孤傲苍狼" />
<input type="submit" value="post方式提交">
</form>
网友评论