一: 过滤器: 可以把”不和谐”的东西给过滤掉
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>的先后顺序来决定. ![过滤器的的先后执行顺序示意图](https://img-/0310104230663?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
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.登陆检查过滤器
![登录检查的流程图](http://img./0310170822918?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
检查登录过滤器
//登录检查过滤器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赋予敏感字过滤功能![流程示意图](http://img./0310212548133?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2VpeGluXzQwMTYxNzA4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
给Filter中的request赋予过滤字符的功能
public class MessageRequestWapper extends HttpServletRequestWrapper{public MessageRequestWapper(HttpServletRequest request) {super(request);}//覆盖getParameter方法,使之支持敏感字过滤public String getParameter(String name){//如果参数名为title或contentif("title".equals(name) || "content".equals(name)){//返回过滤之后的title和contentFilterUtil.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系统销毁了.....");}}
@WebListenerpublic class HttpSessionListenerDemo implements HttpSessionListener{public void sessionCreated(HttpSessionEvent se) {System.out.println("会话开始了");}public void sessionDestroyed(HttpSessionEvent se) {System.out.println("会话结束了");}}
@WebListenerpublic 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开发: