一: 过滤器: 可以把"不和谐"的东西给过滤掉
01.过滤器概述
生活中的过滤器:带有过滤功能的净水器,滤纸,香烟的过滤嘴,测试,丈母娘.
程序中的过滤器:在JAVA中最小的程序单元是类,程序中的过滤器就是一个特殊的类
Servelt/Filter是Web的一个组件.
Web中过滤器的作用(简单理解为:过滤器处在客户端和服务端资源之间):
过滤器可以对所有的请求或者响应做拦截操作.
1:以常规的方式调用资源(Servelt/JSP);
2:利用修改过的请求信息调用资源;
3:调用资源之后,但在响应到客户端之前,对响应做出修改;
4:阻止当前资源调用,代之转带其他资源.
02.过滤器的应用
过滤器在开发中的应用:
1):可以对请求中的字符做编码.
2):登录验证过滤器.
3):敏感字(非法文字)过滤.
4):做MVC框架中的前端控制器(处理所有请求共同操作,再分发)
在开发中两个常用的思想:
1):DRY原则: Don't Repeat Yourself.
开发中拒绝代码重复,(重复会带来巨大的维护成本)
2):责任分离原则:各自做各自最擅长的事情.
03:开发和使用Filter
Servlet开发:
1:自定义一个类(XxxServlet),实现于javax.servlet.Servlet接口.
2:实现Servelt接口中的方法(init(初始化方法),service(处理请求))
3:告诉Tomcat来帮我们管理该Servlet程序(1:使用web.xml做配置,2:WebServlet("/资源名")).
<servlet>
<servlet-name>Servlet的别名</servlet-name>
<servlet-class>自定义Servelt的全限定名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlet的别名</servlet-name>
<url-pattern>/资源名</url-pattern>
</servlet-mapping>
注意:此时的url-pattern的文本内容是外界访问Servelt的资源名称.
Filter开发:
1:自定义一个类(XxxFilter),实现于javax.servlet.Filter接口.
2:实现Filter接口中的方法(init(初始化方法),doFilter(处理请求))
3:告诉Tomcat来帮我们管理该Filter程序(1:使用web.xml做配置,2:WebFilter("/资源名")).
<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>
注意:此时的url-pattern的文本内容是Filter对哪一些资源做过滤操作.
如: /hello.jsp :说明当前Filter只会对/hello.jsp做拦截/过滤.
/employee :说明当前Filter只会对/enployee资源做过滤.
/system/* :说明当前Filter只会对以/system/作为前缀的资源路径做拦截.
filterChain(过滤器链):多个过滤器按照一定的顺序,排列起来.
拦截器栈:
--------------------------------------------------------
程序中存在多个过滤器的时候,过滤器的先后执行顺序由谁来决定.
在WEB.xml中:配置的<fiter-mapping>的先后顺序来决定.
过滤器的的先后执行顺序示意图
04.Filter的细节
过滤器的映射细节:
1):filter中的url-pattern的文本内容是Filter对哪一些资源做过滤操作.
如: /hello.jsp :说明当前Filter只会对/hello.jsp做拦截/过滤.
/employee :说明当前Filter只会对/enployee资源做过滤.
/system/* :说明当前Filter只会对以/system/作为前缀的资源路径做拦截.
/* :说明对所有的资源做过滤.
/*.do :对所有以 .do 结尾的资源做拦截
2):Filter的dispatcher(表示对哪些动作作过滤).
<filter-mapping>
<filter-name>FilterDemo1</filter-name>
<url-pattern>/*</url-pattern>
<url-pattern>/x1</url-pattern>
<!-- 只对请求做拦截(默认) -->
<dispatcher>REQUEST</dispatcher>
<!-- 增加对请求转发做拦截 -->
<dispatcher>FORWARD</dispatcher>
<!-- 增加请求包含做拦截 -->
<dispatcher>INCLUDE</dispatcher>
<!-- 增加跳转到错误页面做拦截 -->
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
05.请求编码过滤器CharacterEncodingFilter
Servelt只管 1:获取 2:调用 3:跳转 就行,设置编码交给Filter就行, DRY原则 跟 责任分离原则!
//字符编码过滤器
public class CharacterEncodingFilter implements Filter{
private String encoding;
private Boolean forceEncoding = false;
public void init(FilterConfig config) throws ServletException {
this.encoding = config.getInitParameter("encoding");
forceEncoding = Boolean.valueOf(config.getInitParameter("force"));
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//类型
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//设置编码
//1:应用中没有编码,并且我自己设置了编码.
//2:应用中已经存在编码了但是依然要使用我自己设置的编码:强制使用
if(haslength(encoding) && (req.getCharacterEncoding() == null || forceEncoding)){
req.setCharacterEncoding(encoding);
}
chain.doFilter(req, resp);
}
public void destroy() {
}
private boolean haslength(String str){
return str!=null && !"".equals(str.trim());
}
}
XML配置文件
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com._520it._02_characterencoding.CharacterEncodingFilter</filter-class>
<!-- 设置编码 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 是否强制使用该编码 -->
<init-param>
<param-name>force</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
06.登陆检查过滤器
登录检查的流程图:
检查登录过滤器
//登录检查过滤器
public class CheckLoginFilter implements Filter{
private String[] unCheckUris = {"/login.jsp","/login"};
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
Object user = req.getSession().getAttribute("USER_IN_SESSION");
//当前正在过滤的资源
String requestURI = req.getRequestURI();
if(!Arrays.asList(unCheckUris).contains(requestURI)){
if(user == null){//没有登录
resp.sendRedirect("login.jsp");
return ;
}
}
chain.doFilter(req, resp);
}
public void destroy() {
}
}
从登录界面跳转到的Servlet中
@WebServlet("/login")
public class LoginServelt extends HttpServlet{
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
//把登录信息存储到session中
req.getSession().setAttribute("USER_IN_SESSION",username);
resp.sendRedirect("/welcome.jsp");
}
}
login.jsp登录界面
<form action="/login" method="post">
账号:<input type="text" name="username" required/><br/>
密码:<input type="text" name="password"/><br/>
<input type="submit" value="登录"/>
</form>
welcom.jsp
${sessionScope.USER_IN_SESSION}
<hr/>
<a href="function1.jsp">功能1</a><br/>
<a href="function2.jsp">功能2</a><br/>
<a href="function3.jsp">功能3</a><br/>
Filter的配置文件
<filter>
<filter-name>CheckLoginFilter</filter-name>
<filter-class>com._520it.checklogin.CheckLoginFilter</filter-class>
<init-param>
<param-name>unCheckUris</param-name>
<!-- 以后这样做 对需要检查的放到/system/中来 -->
<param-value>/system/*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CheckLoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
07.敏感字过滤
利用装饰设计模式,给Request.getParameter赋予敏感字过滤功能
流程示意图:
给Filter中的request赋予过滤字符的功能
public class MessageRequestWapper extends HttpServletRequestWrapper{
public MessageRequestWapper(HttpServletRequest request) {
super(request);
}
//覆盖getParameter方法,使之支持敏感字过滤
public String getParameter(String name){
//如果参数名为title或content
if("title".equals(name) || "content".equals(name)){
//返回过滤之后的title和content
FilterUtil.filter(super.getParameter(name)); //FilterUtils就是过滤的代码,现在先知道就行
}
return super.getParameter(name);
}
}
过滤器(filter)使用
@WebFilter("/*")
public class MessageFilter implements Filter{
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//把不具有处理敏感字的请求对象换成可以处理敏感字的请求对象.
HttpServletRequest req = (HttpServletRequest) request;
HttpServletRequest requestWapper = new MessageRequestWapper(req);
//放行
chain.doFilter(requestWapper, response);
}
public void destroy() {
}
}
二: Listener(监听器)
Web的另一大组件:Listener(监听器).
Web中的监听器,主要用于监听作用域对象的创建,监听作用域对象属性的添加/删除/替换:
1):监听作用域对象的创建和销毁.
ServletRequestListener:监听请求对象的创建和销毁.
HttpSessionListener:监听会话对象(session) 的创建和销毁
ServletContextListener:监听应用的创建和销毁.
2):监听作用域对象的属性的添加/删除/替换.
ServletRequestAttributeListener: 监听request作用域中属性的添加/删除/替换.
HttpSessionAttributeListener: 监听session作用域中属性的添加/删除/替换.
ServletContextAttributeListener: 监听application作用域中属性的添加/删除/替换.
Web中的监听器组件,没有初始化参数配置如果要解决监听器中的硬编码,只能使用全局的初始化参数.
//监听系统(应用)的启动和销毁
public class ContextLoaderListener implements ServletContextListener{
public void contextInitialized(ServletContextEvent sce) {
System.out.println("Web系统启动了.....");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("Web系统销毁了.....");
}
}
@WebListener
public class HttpSessionListenerDemo implements HttpSessionListener{
public void sessionCreated(HttpSessionEvent se) {
System.out.println("会话开始了");
}
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("会话结束了");
}
}
@WebListener
public class HttpSessionAttributeListenerDemo implements HttpSessionAttributeListener{
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("属性添加"+se.getName()+","+se.getValue());
}
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("属性删除"+se.getName()+","+se.getValue());
}
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("属性替换"+se.getName()+","+se.getValue()+","+se.getSession().getAttribute(se.getName()));
}
}
预习,精通Struts2的hello开发: