简介
我们知道servlet与jsp的三大主件是什么吗?对了,servlet,listener,filter,servelt我们都快玩烂了,话不多说,咱们来看看listener和filter的使用。
one by one
listener
JavaWeb中的监听器
事件源:三大域!
ServletContext
生命周期监听:ServletContextListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
void contextDestroyed(ServletContextEvent sce):销毁Servletcontext时
属性监听:ServletContextAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
void attributeAdded(ServletContextAttributeEvent event):添加属性时;
void attributeReplaced(ServletContextAttributeEvent event):替换属性时;
void attributeRemoved(ServletContextAttributeEvent event):移除属性时;
HttpSession
生命周期监听:HttpSessionListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
void sessionDestroyed(HttpSessionEvent se):销毁session时
属性监听:HttpSessioniAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
void attributeReplaced(HttpSessionBindingEvent event):替换属性时
void attributeRemoved(HttpSessionBindingEvent event):移除属性时
ServletRequest
生命周期监听:ServletRequestListener,它有两个方法,一个在出生时调用,一个在死亡时调用;
void requestDestroyed(ServletRequestEvent sre):销毁request时
属性监听:ServletRequestAttributeListener,它有三个方法,一个在添加属性时调用,一个在替换属性时调用,最后一个是在移除属性时调用。
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过滤器
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter不“放行”,那么就不会执行用户请求的Servlet。
其实可以这样理解,当用户请求某个Servlet时,Tomcat会去执行注册在这个请求上的Filter,然后是否“放行”由Filter来决定。可以理解为,Filter来决定是否调用Servlet!当执行完成Servlet的代码后,还会执行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 {
}
}
我们来看图说一下他的执行流程:
解决全站字符乱码(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>
哦了,第一个案例就算完事了。
动态页面静态化
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(String language, String country)
我们在来看一下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个配置文件就哦了。