1.javaweb三大组件:servlet,listener,filter;都需要在web.xml中配置(除了两个感知监听器)。

2.服务器端小程序每个Servlet都是唯一的,能处理的请求是不同的(比如登录,查询);前面的调度由tomcat完成;要完成获取请求数据,处理请求,完成响应的任务。

3.实现servlet的三种方法:javax.servlet.Servlet接口,GenericServlet抽象类(service方法待实现),HttpServlet类(常用)。

4.Servlet接口5大方法:其中3个生命周期方法不由我们来调用,由Tomcat调用;对象也不用我们来创建,Tomcat创建。
4.1:init(ServletConfig):生命周期方法,在对象创建之后只执行一次;当第一次被请求才被创建;
4.2:destroy():生命周期方法,在servlet对象被销毁之前调用,只调用一次;比如IO流等释放(很少);服务器被关闭时调用;
4.3:service(ServletRequest,ServletResponse):生命周期方法,被调用多次用来处理请求;
4.4:getServletConfig()(有用),getServletInfo()(无用)。

5.浏览器如何访问Servlet:必须把Servlet绑定到一个路径(web.xml配置):<servlet>name,class</servlet>,<servlet-mapping>name,url-pattern</servlet-mapping>,其中pattern必须/开头。

6.Servlet单例,线程不安全,效率高。

7.ServletConfig接口:对应的就是web.xml里的本Servlet的配置信息被xml解析器解析后,加载到里面;返回的实例的实现类是Tomcat提供的;
7.1:getServletName()(几乎没用);
7.2:getServletContext()(有用);
7.3:getInitParameter[Names()]:初始化参数相关

8.ServletRequest(Tomcat封装的请求信息),ServletResponse(设置状态码,设置响应头,发送html代码)。

9.GenericServlet抽象类:集成了很多ServletConfig的方法(实质也是调用ServletConfig的方法);注意init()的妙用(非生命周期方法与生命周期的方法链在一起);这个类的源代码可在Tomcat源码里看到。

10.HttpServlet类:是抽象类但没有抽象方法;在http包里,重载了两个service()方法,一个是生命周期方法,一个参数是HttpServletRequest;生命周期的service()会强制转换两个参数类型再调用非生命周期service()方法;非生命周期service()方法会根据request得到请求方式,分别调用doGet()或doPost()方法。如果没覆盖着两个方法且被调用,出现405。

11.Myeclipse可直接右键新建Servlet,可自动生成web.xml配置以及自动列出要覆盖的方法。

12.Servlet细节:
12.1:servlet的线程安全问题:不要创建成员变量,创建局部变量即可;或者创建无状态成员变量;或者有状态成员变量但只读的;
12.2:服务器启动时即创建servlet,web.xml中配置<load-on-startup>即可(但很少有这种需求);
12.3:servlet-mapping的<url-pattern>可以写多个或者匹配多个(用*)(以前没有三大组件,一般Sevlet需要充当过滤器,所以需要多个路径)。

13.web.xml文件(了解):每个项目都继承自Tomcat里conf下的web.xml文件:
13.1:DefaultServlet,匹配/,优先级别最低,负责给出404;
13.2:JspServlet,匹配*.jsp,*jspx;
13.3:session-timeout配置,30分钟;
13.4:mime类型和其真实类型。

14.请求与实现:反射,通过url找名字,找到类名ClassForName,创建对象newInstace,调用方法getMethod;反射总是与配置相出现。

15.域对象:传递数据;javaweb四大域对象(作用域从小到大):PageContext,ServletRequest,HttpSession,ServletContext;JSP含有全部,Servlet只含其中3个。
15.1:ServletContext域,即application域,整个web应用都存在,可以在web.xml中配置初始值,接口可以访问服务器静态内容文件,线程不安全;
15.2:Httpsession域,即session域,在会话期间都存在,服务器为每个浏览器开辟专用内存,把会话号返回浏览器的cookie;
15.3:ServletRequest域,在请求存在,数据只使用一次的放在这里,比如servlet产生给jsp显示的数据;
15.4:PageContext域,即page域,作用在jsp页面。

16.ServletContext(重要):又名application;一个项目一个,可以在多个servlet之间传递数据;与Tomcat共存亡;
16.1:获得:通过ServletConfig或者GenericServlet类;HttpSession类,ServletContextEvent类;
16.2:内部是一个Map,存属性,取属性,移除属性等;演示在一个Servlet存,另一个Servlet读;
16.3:可以获取公共参数<context-param>,之前Servlet获取的只是为自己所用的局部参数;getInitParameter(String);
16.4:获取资源的真实路径(重要):得到有盘符的路径,getRealPath("/index.jsp");然后可以创建File类对象进行后续操作;
16.5:获取资源流:把资源以输入流的方式获取,getResourceAsStream("/a.txt");
16.6:获取指定目录下所有资源路径:getResourcePaths("/WEB-INF")。不会进入子目录。

17.ServletContext应用:写一个Servlet,根据servletContext的特点,统计所有Servlet的访问量,再利用response对象向浏览器输出response.getWriter().print()。

18.获取类路径下的资源:/WEB-INF/classes和/WEB-INF/lib下每个jar包;注意src下的东西会拷贝到classes目录下;
18.1:相对/classes目录:this.getClass().getClassLoader();然后getResourceAsStream("a.txt");从流到字符串需要利用commons-io包的工具;
18.2:(复杂,不常用)相对class文件所在目录:this.getClass().getResourceAsStream("a.txt");/a.txt加了/则是相对于/classes目录;
18.3:(不会这么用,有ServletContext.getRealPath("/index.jsp"))获取index.jsp内容:this.getClass().getResourceAsStream("/../../index.jsp")。

19.BaseServlet:希望在一个Servlet写多个请求处理方法;用户发出请求给出参数确定调用的方法;自定义处理方法的函数签名要与service()相同;
19.1:service()中:从req.getParameter()获取用户指定的处理方法名;然后if-else判断执行;
19.2:接上,得到方法名,先获取当前对象,然后getMethod(方法名,参数类型)得到对象;调用method.invoke(this,req,resp);
19.3:接上,可以将反射的处理放到一个抽象类里然后被不同的Servlet继承,这样只需要实现不同的处理方法即可;
19.4:接上,若希望自定义方法处理完后实现转发或重定向,则在自定义方法返回String,在抽象类service()的invoke后加上判断逻辑;然后转发req.getRequestDispatcher(路径).forward(req,resp);重定向resp.sendRedirect(req.getContextPath()+path)。

-------------------------------------监听器------------------------------------

1.监听器:很少用;比如AWT里的ActionListener,XML解析的SAX;都是接口,里面放自定义的代码;需要注册;发生特定事件时执行;

2.观察者:事件源,事件,监听器(可能有多个方法)。

3.javaWeb中的监听器:事件源是三大域;每个域都有两个监听器:XXXListener(两个方法,事件是生和死),XXXAttributeListener(三个方法,事件为添加,替换和移除属性);
3.1:ServletRequest:请求动态资源即创建;
3.2:HttpSession:一个项目可有0或多个session;执行了req.getSession()就会创建;
3.3:ServletContext:服务器启动创建,服务器关闭销毁。

4.实现ServletContext生命周期监听器:
4.1:实现ServletContextListener接口;
4.2:在web.xml注册<listener>,写明实现类即可;
4.3:用处:放一些初始化数据库数据的代码,关闭的时候删掉这些临时数据;IOC这里放完成工厂注入的代码。

5.上述方法的参数都有事件对象,如:ServletContextEvent对象,只有一个方法getServletContext();HttpSessionEvent对象,getSession()方法;都是汇报事件源用。

6.实现ServletContextAttributeListener属性监听器:
6.1:使用eclipse选择实现该接口,自动在web.xml里注册;
6.2:添加、修改、移除属性三个方法都有参数ServletContextAttributeEvent对象,getName(),getValue(),getServletContext()方法。

7.感知监听器HttpSessionBindingListener:添加到JavaBean上;与HttpSession相关;无需在web.xml中注册;感知自己是否被session添加或移除;
7.1:比如一个简单User类,实现了该接口的两个方法valueBound(HttpSessionBindingEvent)和valueUnbound(HttpSessionBindingEvent);

8.感知监听器HttpSessionActivationListener:也是添加到JavaBean,还要实现Serializable接口;无需注册;能感知自己是否随session被钝化和活化
8.1:Session的序列化和反序列化:在服务器启停的时候发生;禁用该功能在Tomcat的conf的context.xml文件添加<Manager pathname=""/>;
8.2:钝化和活化:太长时间不活跃的session从内存到磁盘;配置参数也是在context.xml(全局生效);活化后文件还存在;
8.3:两个方法sessionWillPassive(HttpSessionEvent)和sessionDidActivate(HttpSe ssionEvent);监听8.2的事件;
8.4:这个监听器基本没啥用。

----------------------------------过滤器---------------------------------

1.在一组资源(jsp,servlet,css,html等)前面执行;可以让请求获得资源,也可以不获得;拦截一组请求。

2.实现:实现Filter接口,在web.xml配置;单例的;
2.1:方法init(FilterConfig):服务器启动就创建,创建之后马上执行,初始化工作;
2.2:方法doFilter(ServletRequest,ServletResponse,FilterChain):
2.3:destroy():服务器关闭,非内存资源的释放,一般用不上;
2.4:配置:与servlet相同;一般<url-pattern>都含有*,;也可用<servlet-name>指定一个或多个具体的servlet。

3.相关类:
3.1:FilterConfig:与ServletConfig类似,获取过滤器名字,获取初始化参数和名字,获取ServletContext;
3.2:FilterChain:方法doFilter(ServletRequest,ServletResponse);放行。

4.多过滤器:FilterChain的doFilter()方法,表示执行目标资源或执行下一过滤器(如有)。

5.四种拦截方式:请求REQUEST;转发FORWARD;包含INCLUDE;错误ERROR;
5.1:配置:在<filter-mapping>里写<dispatcher>,指明上面四种之一,默认是请求;
5.2:错误是去往web.xml里配置的<error-page>的时候被拦截。

6.<filter-mapping>的放置顺序就是多个过滤器的执行顺序。

7.应用场景:考虑把多个Servlet都要执行的代码,放到Filter中;
7.1:预处理:设置编码req.setCharacterEncoding(),一般都放行;
7.2:条件判断:用户是否登录,IP是否禁用的判断;
7.3:后续处理:在目标资源执行后的处理,比如输出数据的处理,如动态页面静态化。

8.案例1:分IP统计网站的访问次数;
8.1:统计所有资源的访问,放在fliter;不做拦截;
8.2:统计数据放哪里?Filter要用,页面显示要用;整个项目就用同一个;ServletContext;
8.3:ServletContext的初始化在哪里?用监听器;在里面放一个统计ip的map;
8.4:材料:静态资源,filter,listener。

9.案例2:粗粒度权限控制;
9.1:细粒度控制,RBAC基于角色的权限控制;用户表,角色表,权限表,以及用户与角色对应的表,角色与权限对应的表;
9.2:判断有没有登录,总要使用到session;注意HttpServletRequest才能得到session,filter里只是ServletRequest;
9.3:只区分游客,会员和管理员:公共资源给所有人访问,会员资源放一个文件夹一个filter控制,管理员资源放一个文件夹被另一个filter控制;
9.4:材料:index.jsp,登录页面,会员资源,管理员资源;会员filter,管理员filter,登录校验Servlet(判断,在session放信息,回到index)。

10.案例3:解决全站字符乱码,所有资源的POST和GET访问都要解决;
10.1:POST乱码的处理(setCharacterEncoding()),GET乱码的处理(getParameter(),new String()),和响应内容乱码的处理;
10.2:这些公共处理代码放filter;但难点在于GET的处理:a.不知道Servlet获取的参数名字;b.设置完了不知道怎么回传给对应的Servlet;
10.3:解决GET:掉包request,写装饰类,增强getParameter(String);
10.3.1:实现HttpServletRequest接口,实现其所有方法;利用构造方法传入一个HttpServletRequest类型保存,然后利用其实现其他方法;
10.3.2:增强方法的写法和之前一样;
10.3.3:chain.doFilter()传入自己增强的req即可;
10.3.4:实现接口麻烦,继承HttpServletRequestWrapper类,只需写getParameter(String)即可。

11.案例4:页面静态化;网站有一些内容是不变的不需要查数据库,比如书籍的类别;首次查询查数据库,保存到html,二次查询直接显示;
11.1:材料:link.jsp(查询所有,查询SE分类,查询EE分类...的链接);显示页面;BookService/Servlet;BookDao;Book实体;
11.2:步骤:创建数据库表;导入jar包;创建jsp;
11.3:BookServlet:继承BaseServlet,从req获得参数,调用Dao实现findAll(),findByCategory(),把结果req.setAttribute(),跳转到show.jsp;
11.4:BookDao:写sql语句并查询,返回List<Book>;
11.5:填充jsp,c3p0的xml文件配置数据库连接信息;
11.6:实现一个filter,把首次访问servlet的输出保存到html,再重定向到html;二次访问直接重定向,filter不再放行访问Servlet(判断);
11.7:准备一个文件夹放中间html;servletContext.getRealPath()得到的是带盘符的路径;req.getContextPath()得到的是项目名称;
11.8:输出页面是response的out,掉包,换getWriter(传html路径)流与html文件绑定而不是浏览器,继承HttpServletResponseWrapper,这样show.jsp在使用out的时候以为在写浏览器,其实写到中间文件;最后重定向到自己的中间文件;解决乱码也在show.jsp设置编码即可。

12.案例3和案例4都是利用filter的拦截特性,在chain.doFilter(req,resp)做手脚,传入自己改良的req对象或resp对象(装饰类)实现自己的功能。