监听器与过滤器

简介

我们知道servlet与jsp的三大主件是什么吗?对了,servlet,listener,filter,servelt我们都快玩烂了,话不多说,咱们来看看listener和filter的使用。

one by one

listener

JavaWeb中的监听器

  事件源:三大域!
ServletContext

生命周期监听:ServletContextListener,它有两个方法,一个在出生时调用,一个在死亡时调用;


void contextInitialized(ServletContextEvent sce):创建SErvletcontext时
void contextDestroyed(ServletContextEvent sce):销毁Servletcontext时


属性监听:ServletContextAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。


void attributeAdded(ServletContextAttributeEvent event):添加属性时;
void attributeReplaced(ServletContextAttributeEvent event):替换属性时;
void attributeRemoved(ServletContextAttributeEvent event):移除属性时;


HttpSession

生命周期监听:HttpSessionListener,它有两个方法,一个在出生时调用,一个在死亡时调用;


void sessionCreated(HttpSessionEvent se):创建session时

void sessionDestroyed(HttpSessionEvent se):销毁session时


属性监听:HttpSessioniAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。


void attributeAdded(HttpSessionBindingEvent event):添加属性时;
void attributeReplaced(HttpSessionBindingEvent event):替换属性时
void attributeRemoved(HttpSessionBindingEvent event):移除属性时


ServletRequest

生命周期监听:ServletRequestListener,它有两个方法,一个在出生时调用,一个在死亡时调用;


void requestInitialized(ServletRequestEvent sre):创建request时

void requestDestroyed(ServletRequestEvent sre):销毁request时


属性监听:ServletRequestAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。


void attributeAdded(ServletRequestAttributeEvent srae):添加属性时
void attributeReplaced(ServletRequestAttributeEvent srae):替换属性时
void attributeRemoved(ServletRequestAttributeEvent srae):移除属性时


javaWeb中完成编写监听器:
写一个监听器类:要求必须去实现某个监听器接口;
注册,是在web.xml中配置来完成注册!


事件对象:
ServletContextEvent:ServletContext getServletContext()
HttpSessionEvent:HttpSession getSession()
ServletRequest:
ServletContext getServletContext();
ServletReques getServletRequest();
ServletContextAttributeEvent:
ServletContext getServletContext();
String getName():获取属性名
Object getValue():获取属性值
HttpSessionBindingEvent:略
ServletRequestAttributeEvent :略


感知监听(都与HttpSession相关)
它用来添加到JavaBean上,而不是添加到三大域上!
这两个监听器都不需要在web.xml中注册!


HttpSessionBindingListener:添加到javabean上,javabean就知道自己是否添加到session中了。

这是如何在xml中部署的形式
<listener>
<listener-class>cn.itcast.listener.MyServletContextListener</listener-class>
</listener>

由于listener使用的并不是很多,所以我们就不用代码进行演示了。

filter过滤器

过滤器JavaWeb三大组件之一,它与Servlet很相似!不它过滤器是用来拦截请求的,而不是处理请求的。
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter不“放行”,那么就不会执行用户请求的Servlet。
其实可以这样理解,当用户请求某个Servlet时,Tomcat会去执行注册在这个请求上的Filter,然后是否“放行”由Filter来决定。可以理解为,Filter来决定是否调用Servlet!当执行完成Servlet的代码后,还会执行Filter后面的代码。
我们在编写过滤器时要实现Filter接口该接口形式如下:
public class INFilter implements Filter {

	public void destroy() {
		
	}
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
	}
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}
 
}

我们来看图说一下他的执行流程:


话不多说,我们看两个filter的实现:

解决全站字符乱码(POST和GET中文编码问题)

上代码:
public void doFilter(ServletRequest request, 
			ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest req = (HttpServletRequest)request;
		
		if(req.getMethod().equalsIgnoreCase("post")) {
			req.setCharacterEncoding("utf-8");
			chain.doFilter(req, response);
		}else {
			//如果是get请求的话我们怎么进行转码,我们可以使用装饰者模式,对request的getParamter()、
			//方法进行增强,实现转化。我们在给servlet传递一个我们装饰过后的request酒神不知鬼不觉的解决了
			EncodingRequest enreq = new EncodingRequest(req);
			chain.doFilter(enreq, response);
		}
		
	}

/*
 * 我们直接继承HttpServletRequestWrapper,因为他也只是实现了HttpServletRequest接口
 * 如果我们自己实现是不是傻呢。我们只需要对我们要加强的方法进行重写即可
 */
public class EncodingRequest extends HttpServletRequestWrapper{
	
	public EncodingRequest(HttpServletRequest request) {
		super(request);
		
	}
	@Override
	public String getParameter(String name) {
		String param = super.getParameter(name);
		if(param != null && !param.trim().isEmpty()){
			byte[] b;
			try {
				b = param.getBytes("iso-8859-1");
				param = new String(b,"utf-8");
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e);
			}
		}
		return param;
	}

}

好了,万事具备,只欠东风,我们就差部署filter了
<filter>
  	<filter-name>encodingFilter</filter-name>
  	<filter-class>filter.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>encodingFilter</filter-name>
  	<url-pattern>/AServlet</url-pattern>
  </filter-mapping>
哦了,第一个案例就算完事了。

第二个
动态页面静态化
所谓动态页面静态化其实就是当我们初次访问时将response的printwriter指向我们本地硬盘,为了实现这一点,我们就对使用对response的getWriter() 方法的装饰了,带到下一次访问时直接跳转到该静态页面即可。
上代码:
public void doFilter(ServletRequest request,
			ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		/*
		 * 我们使用这个过滤器来进行页面的静态化
		 * 1 我们判断是否是第一次访问该页面,如果是则调用doFilter方法并写入硬盘
		 * 否则读入该文件
		 */
		//进行类型转化
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		
		String name = req.getParameter("category");
		name = name + ".html";
		String path = filterConfig.getServletContext().getRealPath("/htmls");
		path = path + "\\" + name;
		File file = new File(path);
		if(file.exists()) {
			resp.sendRedirect(req.getContextPath() + "/htmls/" + name);
			return;
		}
		else{
			StaticResponse s = new StaticResponse(resp, path);
			chain.doFilter(req, s);
			s.sendRedirect(req.getContextPath() + "/htmls/" + name);
			return ;
		}
	}


public class StaticResponse extends HttpServletResponseWrapper{
	private PrintWriter pw;
	public StaticResponse(HttpServletResponse response, String path) {
		super(response);
		try {
			this.pw = new PrintWriter(path, "utf-8");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	public PrintWriter getWriter() {
		
		return pw;
	}
}

哦了,在部署一下就实现了!!



对了,我们中途在插入一点,那就是

国际化的内容

国际化所涉及的类有Locale类和ResourceBundle类

我们先来说一下Locale类
我一一般常见的形如   en_US   下划线前是语言,下划线后是国家
Locale类的构造器如下:
Locale(String language, String country) 
我们在来看一下ResourceBundle类

我们如何得到ResourceBundle类的对象呢?使用如下静态方法;
getBundle(String baseName, Locale locale) 
好了,我们得到了资源类的对象就可以使用如下方法获得属性了:
getString(String key) 
我们下面来演示一下过滤器中进行国际化的步骤:

/*
 * 我们首先从request中获取名为request_locale的参数,如果存在则使用参数值创建locale对象,
 * 并将其保存到session中
 * 如果没有,则到session中获取,
 * 如果还没有,那摩我们只能使用浏览器的推荐类型了,即使用request.getLocale()方法,并保存到session中
 * 
 */
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		Locale locale = null;
		String l = req.getParameter("request_locale");
		if(l != null && !l.trim().isEmpty()) {
			String[] strs = l.split("_");
			locale = new Locale(strs[0], strs[1]);
			req.getSession().setAttribute("locale", locale);
		}else{
			HttpSession session = req.getSession();
			locale = (Locale) session.getAttribute("locale");
		}
		if(locale == null) {
			locale  = req.getLocale();
			req.getSession().setAttribute("locale",locale);
		}
		I18N.setLocale(locale);
		chain.doFilter(req, resp);
		
	}

好了,让我们写一下I18N类:
public class I18N {
	/*
	 * res是有我们指定的,这是基本名称,我们需要创建几个属性文件,文件名为:language_语言_国家.properties
	 * 我们通过filter来设置locale静态对象,继而创建了bundle对象。
	 */
	private static Locale locale ;
	private static String res = "language";
	private static ResourceBundle bundle;
	
	public static String getText(String key) {
		return I18N.bundle.getString(key);
	}
	public static void setLocale(Locale locale) {
		I18N.locale = locale;
		setBundle();
	}
	private static void setBundle() {
		ResourceBundle bundle = ResourceBundle.getBundle(res, locale);
		I18N.bundle = bundle;
	}
}

我们来写一个登录界面吧:
<center>
	   	<form action="" method="post">
	   		<tr>
	   			<td><%=I18N.getText("name") %></td>
	   			<td><input type="text" name="name"></td>
	   		</tr> <br/>
	   		<tr>
	   			<td><%=I18N.getText("password") %></td>
	   			<td><input type="password" name="password"></td>
	   		</tr><br/>
	   		<tr>
	   			<td><input type="submit" value="<%=I18N.getText("log") %>"></td>
	   			<td><input type="submit" value="<%=I18N.getText("reg") %>"></td>
	   		</tr><br/>
	   	</form>
   	</center>


好了,在来写N个配置文件就哦了。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值