Servlet 和 JSP 基础

--Servlet技术是使用Java语言开发的一套组件规范,
    是由一个单独的线程来处理的。
--组件是对部分功能的实现,不能单独运行,
    对这些组件进行管理、创建、销毁的运行环境称为容器。
--这些容器有:Tomcat、Weblogic、JBoss等
--Servlet 的实现
    1)实现接口Servlet
    2)实现抽象类GenericServlet
    3)实现抽象类HttpServlet
    -- HttpServlet的父类——>GenericServlet 实现了接口 -->Servlet
>>>>>>>>>>>>1.报错和解决<<<<<<<<<<<<<<<<<<<<<<
1. 404错误产生原因及解决方法
    --产生原因:Web服务器(容器)根据请求地址找不到对应资源
>>以下情况会出现404错误
    1)输入的地址有误(应用名大小写不正确,名称拼写不正确)
    2)在web.xml文件中<servlet>和<servlet-mapping>中的两个<servlet-name>不一致
    3)没有将工程部署到Tomcat的webapps下面
    4)Web工程部署时的结构没有遵循Servlet的规范
2. 405错误产生原因及解决方法
    --产生原因:容器找不到service方法来处理请求。
>>以下情况容器都将视为没有找到service()方法
    1)service方法名写错,字母顺序不对或大小写错误
    2)service方法参数类型与标准不一致,或参数顺序与标准不一致。
        一定是先HttpServletRequest,然后是HttpServletResponse类型
    3)service方法异常、返回值类型与标准不一致,
        一定是抛出ServletException、IOException。返回值类型是void。
3. 500错误产生原因及解决方法
    --错误原因:请求的Servlet在执行service方法的过程中出现了错误,
        程序不能继续运行了
>>以下情况容器都将视为500的一种情况:
    1)Servlet没有继承HttpServlet或实现Servlet接口
    2)web.xml文件中的<servlet-class>写错,与真正的包名类名不符
    3)service方法中的代码运行时抛出异常

>>>>>>>>>>>>>>>>2.HTTP协议<<<<<<<<<<<<<<<<<<<<<<
--HTTP协议是HyperText Transfer Protocol,即超文本传输协议 
--由W3C指定的一种应用层协议
--规范浏览器和web服务器如何通信及通信的数据格式
>>>一次请求一次连接,尽量降低服务器的压力
1.HTTP如何通信
    1)建立连接
    2)请求数据
    3)响应数据
    4)关闭连接
2.数据包格式:
  2.1请求包数据
    --请求行:请求基本的信息
      --请求方式+请求资源路径+协议类型+版本
    --消息头:请求数据的描述信息
    --实体内容:请求的数据
  2.2响应包数据
      --状态行:响应基本的信息
      --协议类型+版本+状态码+状态描述
    --消息头:响应数据的描述信息
    --实体内容:响应的数据

>>>>>>>>>>>>>>>>3.请求方式GET和POST<<<<<<<<<<<<<<<<<<<<<<
1.GET
    --使用请求路径传参,将参数附加在路径上发送服务器
    --参数在传递过程中可见,隐私性差
    --请求路径空间有限,只能携带少量参数(<2K)
     >>所有默认的请求都是GET请求
2.POST
    --使用实体内容传参
    --参数在传递过程中不可见,隐私性好
    --实体内容专门用来传参,大小没有限制
    >>在form上增加method="post"时
3.获取GET和POSt传到服务器的参数
    --服务器端处理GET和POST请求是没有分别的
    --使用方法:
        --req.req.getParameter(表单name属性) 返回字符串
        --req.getParameterValues(表单name属性) 返回字符串数字组
            --如果同一个name 对应多个值就用此方法
            --即用于获取表单中一组参数名相同的控件提交的数据组
4.解决乱码问题
  4.1 解决服务器端乱码
    --方案1:
        --get/post:让Serverlet接收乱码String,
            用ISO8859-1将其还原称byte,再用UTF-8将其转成String
            --byte[] bs = user.getBytes("iso8859-1");
            --user = new String(bs,"utf-8");
        --优点:万能   --缺点:麻烦
    --方案2:
          get:修改Tomcat的配置文件server.xml,65行左右
          --优点:简单
    --方案3:
        post: 在获取请求参数之前,设置
            --req.setCharacterEncoding("utf-8");
        优点:简单
    ◆注:一般采用后面两种方式
  4.2 解决浏览器端乱码
      --设置发送的编码规则
          --res.setContentType("text/html;charset=utf-8");
5.表单的action路径问题
--表单绝对路径:
    有固定格式:/项目名/Servlet路径
--表单相对路径:
    --没有固定格式,需要写出当前访问和目标Servlet之间的相对位置
    --因为打开网页和访问Servlet都由浏览器实现,
    --站在浏览器的角度来说:
        --网页访问路径:/Servlet2/register.html
        --Servlet访问路径:/Servlet2/register
        --因为他们是平级,所以相对路径是register

>>>>>>>>>>>>>>>>4.重定向<<<<<<<<<<<<<<<<<<<<<<
1、重定向:**重要**
>>实用场景
    1)经典实用场景:(如百度搜索)
        --不同服务器之间的跳转
    2)扩展使用场景
        --解决1个项目内,2个独立组件之间跳转问题
    3)重定向的一般使用场景
        --增加、修改、删除后重定向到查询。
--res.sendRedirect(目标地址);
2、路径
--指部署代码的访问路径    
--静态资源(html/css/js/img等)就是文件在Tomcat存储的位置
--动态资源(servlet)就是Servlet的访问路径(网名)
--项目名
    --req.getContextPath();
--网页名
    --req.getServletPath();
--在项目中的网页的绝对路径
    --req.getRequestURI();
--外网访问全路径
    --req.getRequestURL();
--在web中
    URL:资源的真名
    URI:资源的名称
    --URI包含URL
3.Servlet访问路径有3种方式:
    不同的方式其处理请求的能力不同
    1)精确匹配(/abc)
        --只有访问/abc路径能处理请求
        --此Servlet只能处理一个请求
    2)通配符(/*)
        -所有的路径都可以访问此Servlet
        -此servlet能处理所有请求
    3)后缀(*.hi)
        --所有以hi为后缀的路径都可以访问此Servlet
        --此Servlet可以处理多个请求
        --不允许以斜线开头

>>>>>>>>>>>>>>>>>>servlet特性<<<<<<<<<<<<<<<<<<<
1.servlet生命周期
    1)实例化(new )
    2)初始化(init())
    3)就绪
    4)销毁(destory())
>>默认第一次访问Servlet时会创建并初始化它
>>可以修改成启动Tomcat时就创建并初始化它
>>对于某个类型的Servlet来说,第1,2,4步只会执行一次,
    第三步可以执行多次,因此某个类型Servlet在tomcat内
    只有一个实例,即单例。

2.  servletconfig 和 ServletContext
    --开发servlet时可能需要读取一些参数
    --可以自己写配置文件及工具来设置这些参数
    --也可以直接使用web.xml做配置文件,
        并使用config和context对象做工具来读取其参数。
    --每个servlet就像一个学生,config就像他的tts账号。
        即config和servlet是一对一的关系,每个servlet都会有一个config对象。
    --context就是教室,可以为所有学生服务,
        即context和servlet是一对多的关系,项目中只有一个context,为所有的servlet服务。
    config:
    <servlet>
          <servlet-name>login</servlet-name>
          <servlet-class>web.LoginServlet</servlet-class>
          <!-- 给当前Servlet预置一个参数,此参数在调用Servlet.init方法之前,被对应的config对象读取,一个init-param 
          标签对应一条数据-->
          <init-param>
              <param-name>maxOnline</param-name>
              <param-value>1000</param-value>
          </init-param>
      </servlet>

    --ServletConfig cfg = getServletConfig();
    --String maxOnline = cfg.getInitParameter("maxOnline");

    --config 典型的使用场景:
        1.假设压偶作一个网游,网限制在线人数。
        2.在用户登录时判断是否已经达到了上线maxOnline 
        3.该参数赢是可以配置的,并且仅仅是在登录的Servlet中使用,因此使用config即可。
    --context 典型使用场景:
        1.项目中包含很多查询功能,如查询员工,部门等
        2.这些查询功能一般都有分页
        3.每页显示的行数(size)是需要可配置的
        4.由于该参数多个功能都要公用,所以用context
        --ServletContext ctx = getServletContext();
        --ctx.setAttribute("count", 0);
    --context的特殊用法:
        1.可以在程序运行的任何阶段你用它来存取变量
        2.其存储的变量可以在多个Servlet间共用
        案例:统计网站流量(访问量)
        
3.Servlet线程安全问题
    1.什么时候会出现线程安全问题
        --多个线程同时修改一份数据时
        --对象、成员变量存储在堆中,多线程共用
        --局部变量存储在栈中,每个线程有自己的栈帧
        >>多个人同时修改对象或成员变量时
    2.如何解决线程安全问题
        --加锁
        synchronized (this) {
            代码块
        }

########################### JSP ################################
--JSP(Java Server Page)是Sun公司制定的一种服务器端动态页面技术的组件规范,
--以“.jsp”为后缀的文件中既包含HTML静态标记用于表现页面,
--也包含特殊的代码,用于生成动态内容。
---JSP的实现底层是TOMCAT自动生成一个类来实现Servlet接口,将JSP转换为java。
-- #JSP是特殊的Servlet#
1.JSP包含三种类型的Java代码:
    --JSP表达式(方便输出)
    --JSP小脚本(完成相对较长的逻辑运算)
    --JSP声明(添加属性或方法)(一般不使用)
2.JSP表达式:最终会成为service()方法中使用out.print语句的输出
    实例:     <%=3+5%>
            <%=add()%>
            <%=xx.getName()%>
            <%=xx.getName()+“abc”%>
    ◆注意:表达式结束不需要写分号。
3.JSP小脚本:最终会成为Servlet中Service方法的一部分
    例:
    <table>
    <%
    List<User> allUser = (List<User>)request.getAttribute(“users“);
    for(User u : allUser){
    %>
        <tr>
            <td> <%=u.getId()%>    </td>
            <td> <%=u.getName()%>  </td>
        </tr>
    <%    }    %>
    </table>
4. JSP页面中的指令
    --语法:<%@ 指令名  属性=值 %>
    --常用指令包含以下三种:page、include、taglib
    4.1 page指令
        --可以实现在JSP页面中导入要用到的Java包,
            也可以对页面的一些属性进行设置
        ---例1:
            <%@ page import=“java.util.*,java.sql.*“%>
        ---例2:
            <%@ page contentType=“text/html;charset=utf-8“%>
            <%@ page pageEncoding=“UTF-8“%>
    4.2 include指令
        --主要用于将其他页面包含在另一个页面之中
        ---例:<%@ include file=“header.html” %>
    4.3 taglib指令
        --主要用于在JSP中导入JSTL
        --例:<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
5.JSP页面中的隐含(九个)对象**重要**
    request、
    response、
    out、
    session、
    application(ServletContext)、
    pagecontext、
    page、
    config、
    exception

>>>>>>>>>>>>>>>>>>>>>>>JSP开发要点<<<<<<<<<<<<<<<<<<<<<
1.转发
  --在Web服务器端处理用户请求的时候,会有需要多个Web组件配合才能完成的情况。
      一个Web组件(Servlet/JSP)将未完成的处理通过容器转交给
      另外一个Web组件继续完成,这个转交的过程叫做转发。
    --常见情况是Servlet负责获取数据,然后将数据转交给JSP进行展现。
    实现转发的步骤:
        步骤一:绑定数据到request对象
            request.setAttribute(String name,Object obj);
        步骤二:获得转发器
            RequestDispatcher rd = request.getRequestDispatcher(String uri);
        步骤三:实现转发
            rd.forward(request,response);
    转发的原理:
    1.请求到达服务器
    2.根据请求信息创建request和response对象
    3.根据请求资源路径找到对应的Servlet执行处理
    4.Servlet在处理过程中从数据库获取到结果信息
    5.Servlet将结果信息绑定在request对象中
    6.Servlet通知容器将req和res对象转交给list.jsp页面继续执行对请求的响应
    7.list.jsp页面被调用并执行时从传递过来的request对象中获取绑定的数据
        生成结果页面
    8.服务器将list.jsp页面的执行结果返回给客户端。
2.重定向和转发的区别
    --重定向:浏览器发送请求到容器访问A,A可以发送一个状态码302和
        一个Location消息头到浏览器,于是浏览器会立即向Location发新的请求。
    --转发:浏览器发送请求到容器访问A,A可以通知容器去调用B。
        转发所涉及的各个Web组件会共享同一个request和response对象,
        而重定向不行。
    --说明:当请求到达容器,容器会创建request对象和response对象。
        当响应发送完毕,容器会立即删除request对象和response对象。
        即,request对象和response对象的生存时间是一次请求与响应期间。
        转发之后,浏览器地址栏的地址不变,重定向会变。
        转发的地址必须是同一个应用内部某个地址,而重定向没有这个限制。
        转发是一件事情未做完,调用另外一个组件继续做;
        而重定向是一件事情已经做完,再做另外一件事情。

########################### EL和JSTL ################################
>>>为什么需要EL和JSTL
    JSP内嵌大量Java代码,增加了页面的维护难度,使用简单的标签来表现
    复杂的逻辑及简单的形式表示运算关系就是EL和JSTL出现的原因。
>>>>> EL表达式
1.Bean属性
    Bean:一个公共的类,按照固定的方式提供属性的get/set访问方式。
    1.实现序列化接口
    2.有get/set方法
2.EL表达式实现方式
    --没有为name属性赋过值,页面输出“”,不会输出null
    1)${对象名.属性名}
        --${user.name}    
        从pageContext、request、session、application中依次查找绑定名为“user”的对象,找到后调用“getName”方法,将返回值输出。
    2)${对象名[“属性名”]} 其他与上面相同
    --对于数组属性的值可以使用如下表达式访问:
        ${user.Array[0]}
3.四个预对象
    --EL表达式在取值的时候,会依次调用pageContext、request、
        session、application的getAttribute()方法
4.指定对象的查找范围
    --例:${sessionScope.user.name}
    --一旦指定了对象所在的范围,那么只会在范围内查找绑定对象,
        不会在找不到的时候再去其他区域中查找了。
    --sessionScope的位置还可以填写pageScope、requestScope、applicationScope。
5.使用EL表达式获取请求参数值
    --以下两种写法分别等价:
        ${param.username} 与 request.getParameter(“username”);
        ${paramValues.city} 与request.getParameterValues("city");

>>>>> JSTL
1.什么是JSTL
    Sun 公司 Java 标准规范的 JSTL 由 apache组织负责维护
2.如何使用JSTL
    ①将标签库对应的jar包拷贝到WEB-INF/lib目录下
    ②使用taglib指令在页面上引入标签的命名空间和前缀,帮助系统定位对应的类。
    --例:<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
3.c 的核心标签
    1)if标签
        <%
            User user = new User();
            user.setName("胡萝卜");
            user.setGender("f");
            request.setAttribute("user",user);
        %>
           姓名:${user.name}<br/>
        性别:
        <c:if test="${user.gender =='m'}" var="rs" scope="request">男</c:if>
        <c:if test="${!rs}">女</c:if>    
     2)choose标签
         --使用choose标签简化多个if标签的判断
         <%
            User user = new User();
            user.setName("胡萝卜");
            user.setGender("x");
            request.setAttribute("user",user);
            %>
        性别:
        <c:choose>
            <c:when test="${user.gender == 'm'}">男</c:when>
            <c:when test="${user.gender =='f'}">女</c:when>
            <c:otherwise>未知</c:otherwise>
        </c:choose>
      3)forEach标签
          --使用forEach标签完成对集合的遍历输出。
          --其中items属性为要遍历的集合,var属性为每次取出来的一个对象,
              varStatus指定当前迭代的状态
          <table>
            <tr>
                <td>序号</td>
                <td>姓名</td>
                <td>年龄</td>
            </tr>
            <c:forEach items="${users}" var="u" varStatus="s">
                <tr>
                    <td>${s.count}</td>
                    <td>${u.name}</td>
                    <td>${u.age}</td>
                </tr>
            </c:forEach>
        </table>

>>>>>自定义标签
--如何开发自定义标签
    1.编写一个继承自SimpleTagSupport的Java类:
        import javax.servlet.jsp.tagext.SimpleTagSupport;
        public class HelloTag extends SimpleTagSupport{}
    2.重写该类的doTag方法,在其中添加处理逻辑:
        import javax.servlet.jsp.JspException;
        import javax.servlet.jsp.JspWriter;
        import javax.servlet.jsp.PageContext;
        import javax.servlet.jsp.tagext.SimpleTagSupport;
        public class HelloTag extends SimpleTagSupport{
                private String info;
                private int qty;
                public void setInfo(String info) {
                    this.info = info;
                }
                public void setQty(int qty) {
                    this.qty = qty;
                }
                @Override
                public void doTag() throws JspException, IOException {
                    PageContext ctx =(PageContext)getJspContext();
                    JspWriter out = ctx.getOut();
                    for(int i=0;i< qty;i++){
                        out.println(info+"<br/>");
                    }
                }
            
        }
    3.在WEB-INF下面新建一个tld文件,用于配置标签说明文件。代码如下:
        <?xml version="1.0" encoding="UTF-8" ?>
        <taglib xmlns="http://java.sun.com/xml/ns/j2ee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
            http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"  
            version="2.0">
        <tlib-version>1.1</tlib-version>
        <short-name>c1</short-name>
        <uri>http://www.tarena.com.cn/mytag</uri>
        <tag>
            <name>hello</name>
            <tag-class>tag.HelloTag</tag-class>
            <body-content>empty</body-content>
            <attribute>
            <name>info</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
            </attribute>
            <attribute>
                <name>qty</name>
                <required>true</required>
                <rtexprvalue>true</rtexprvalue>
            </attribute>
        </tag>
        </taglib>
    4.标签在页面中被引用时的代码如下:
        <%@taglib uri="http://www.tarena.com.cn/mytag" prefix="c1" %>
        //…  …
        <c1:hello info="hello kitty" qty="${1+5}"/>
    5. 标签的运行原理
        --容器依据JSP页面中的uri找到tld文件
            依据标签中的<c1:hello>hello这个名字找到标签类tag.HelloTag。
            接下来实例化该标签,同时属性值赋给参数,调用doTag方法。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    ---报错时使用统一的错误页面
        <!-- 让tomcat统一处理项目中的异常。有两种方式,只能使用一个 -->
        <!-- 第一种方式:在tomcat捕获到某类型异常时,自动转发到某错误页面 -->
        <error-page>
            <exception-type>java.lang.Exception</exception-type>
            <location>/WEB-INF/error.jsp</location>
        </error-page>
        <!-- 2.在tomcat捕获到某编号异常时,自动转发到某错误页面 -->
        <error-page>
            <error-code>500</error-code>
            <location>/WEB-INF/error.jsp</location>    
        </error-page>
        <error-page>
            <error-code>404</error-code>
            <location>/WEB-INF/error.jsp</location>    
        </error-page>
        <error-page>
            <error-code>405</error-code>
            <location>/WEB-INF/error.jsp</location>    
        </error-page>
        <!-- jsp路径写成绝对路径,因为无法确定那个请求中报错。
              另外tomcat直到要转发的jsp一定在当前项目内,
              它会自动在路径前面追加项目名,因此此处路径不要写项目名 -->
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

########################### Cookie和Session ################################
>>cookie和session的用途
    1)通俗的理解
    ---按照如下的规则存储数据:
        ⑴多个请求可以共用这样的数据
        ⑵多个servlet可以共用这样的数据
        ⑶每个浏览器单独存一份数据
    2)专业的理解
    --HTTP是无状态协议:即一次请求对应一次响应,响应结束后连接即断开,
        同一个用户的不同请求对于服务器端来讲并不会认为这两个请求有什么关联性,
        并不会以此区分不同的客户端
    --cookie和session就是管理状态,让服务器记住浏览器的
    状态:用来证明浏览器曾经访问过服务器的数据
>>状态管理两种常见模式
    --状态管理的过程中重要的是数据的保存,只有存下来的数据才能在多次交互中起到记录的作用,
        所以可以按照管理的数据的存储方式和位置的不同来区分状态管理的模式。
    --如果将数据存储在客户端,每次向服务器端发请求时都将存在客户端的数据随着请求发送到服务器端,
        修改后再发回到客户端保存的这种模式叫做Cookie。
    --如果将数据存储在服务器端,并且为这组数据标示一个编号,只将编号发回给客户端。
        当客户端向服务器发送请求时只需要将这个编号发过来,
        服务器端按照这个编号找到对应的数据进行管理的这种模式叫做Session——会话。

>>>>>>>>>>>>>>>>>>>> Cookie <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1.创建cookie
    --Cookie  c = new Cookie(String name,String value);
    --response.addCookie( c );
    ---例:
        Cookie c = new Cookie("username","Lisa");        
        Cookie c2 = new Cookie("city","NewYork");
        response.addCookie(c);
        response.addCookie(c2);
2.获取Cookie
    --Cookie[] request.getCookies();
    ---例:
    Cookie[] cookies =  request.getCookies();
    if(cookies!=null){
        for(Cookie c : cookies){
            String cookieName = c.getName();
            String cookieValue = c.getValue();
        }
    }
3.修改Cookie
    --通过setValue方法将新的数据存入到cookie中,
        然后由response响应对象发回到客户端,对原有旧值覆盖后即实现了修改
    --使用setValue方法修改了Cookie的值,但是不发回到客户端的话,
        也不会实现数值的改变
4.Cookie的生存时间
    --默认是关闭浏览器Cookie自动销毁
    --如果希望关闭浏览器后Cookie仍存在,则可以通过设置过期时间
        使得Cookie存在硬盘上得以保存更长的时间。
    --void setMaxAge(int seconds);
    seconds > 0 :代表Cookie保存在硬盘上的时长
    seconds = 0 : 代表Cookie的生命时长为现在,而这一刻稍纵即逝,
        所以马上Cookie就等同于过了生存时间,所以会被立即删除。
        这也是删除Cookie的实现方式。
    seconds < 0 :缺省值,浏览器会将Cookie保存在内存中。
5.Cookie编码
    --Cookie作为在网络传输的一段字符串文本,只能保存合法的ASCII字符,
        如果要保存中文需要将中文变成合法的ASCII字符,即编码
    --Cookie c = new Cookie("city",URLEncoder.encode("北京","utf-8"));
6.Cookie解码
    --服务器读取客户端经过编码之后的信息时,要想能够正确显示需要
        将信息解码后才能输出。使用URLDecoder的decode()方法即可
    --URLDecoder.decode(c.getValue(),"utf-8")
7.Cookie的路径问题
    1)什么是Cookie的路径问题
    --客户端存储Cookie之后,并不是针对同一个应用访问任何资源时都
        自动发送Cookie到服务器端,而是会进行路径的判断。
    --只有符合路径规范的请求才会发送Cookie到服务器端。
    --客户端在接受Cookie时会为该Cookie记录一个默认路径,
        这个路径记录的是添加这个Cookie的Web组件的路径。
    --如,当客户端向 http://localhost:8080/test/file/addCookie.jsp
        发送请求时创建了cookie,那么该cookie的路径就是 /test/file.
    2)什么时候发送Cookie
    --只有当访问的地址是Cookie的路径或者其子路径时,
        浏览器才发送Cookie到服务器端。
    --如:Cookie的路径是/test/file,那么如果访问的是/test/file/a.jsp 
        或者 /test/file/b/c.jsp时,都会发送Cookie。
        如果访问的是 /test/d.jsp,则浏览器不会发送Cookie。
    3)如何设置Cookie的路径
        --设置Cookie的路径可以使用Cookie的API方法,setPath(String uri);
        ---例:
            Cookie c  = new Cookie(“uname”,“jack”);
            c.setPath(“/test”);
            response.addCookie(c);
    4)Cookie的限制
        (1)Cookie由于存放的位置在客户端,所以可以通过修改设置被用户禁止
        (2)只能保存少量数据,长度是有限制的,一般为4kb左右
        (3)只能保存字符串,不能保留复杂的对象类型数据
        (4)Cookie安全性很低,非常容易通过截取数据包来获取
        (5)网络中传输的内容也会增加网络的传输量影响带宽

>>>>>>>>>>>>>>>>>>>> Session <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1.什么是Session
    服务器为不同的客户端在内存中创建了用于保存数据的Session对象,
    并将用于标识该对象的唯一Id发回给与该对象对应的客户端。
    当浏览器再次发送请求时,SessionId也会被发送过来,
    服务器凭借这个唯一Id找到与之对应的Session对象。
    在服务器端维护的这些用于保存与不同客户端交互时的数据的对象叫做Session。
2.Session创建
    --浏览器首次访问时,服务器会自动给它创建一个session
    --服务器在创建request后,会让request引用这个session
3.获取Session
    --HttpSession session = req.getSession();
4.如何使用Session绑定对象
    --Session作为服务器端为各客户端保存交互数据的一种方式,
        采用name-value对的形式来区分每一组数据
    --void session.setAttribute(String name,Object obj);
    --获取绑定数据或移除绑定数据
        --void session.getAttribute(String name);
        --void session.removeAttribute(String name);
5.如何删除Session对象
    --void  invalidate()
    --该方法会使得服务器端与该客户端对应的Session对象不再被Session容器管理,
        进入到垃圾回收的状态
6. Session超时
    1)什么是Session超时
        --Session会以对象的形式占用服务器端的内存
        --Web服务器缺省的超时时间设置一般是30分钟。
        --一旦Session对象存在的时间超过了这个缺省的时间限制则认为是Session超时,
            Session会失效,不能再继续访问
    2)如何修改Session的缺省时间限制
    --设置session超时的时间:服务器每个一段时间就会检查用户的空闲时间,
          若该用户的空闲时间已经超过了配置的时间,则将它的session销毁,单位为:分钟
          <session-config>
              <session-timeout>10</session-timeout>
          </session-config>
7. Session优缺点
    优点:
        (1)Session对象的数据保存在服务器安全较高
        (2)能够保存丰富的数据类型
        (3)能够保存更多的数据,Cookie只能保存大约4kb的字符串。
    缺点:
    --Session的安全性是以牺牲服务器资源为代价的,
        如果用户量过大,会严重影响服务器的性能。
8.浏览器禁用Cookie的后果
    --Session对象的查找依靠的是SID,而这个ID保存在客户端时是以
        Cookie的形式保存的。一旦浏览器禁用Cookie,那么SID无法保存,
        Session对象将不再能使用。
9.什么是URL重写
    --解决浏览器禁用Cookie
    --浏览器在访问服务器的某个地址时,会使用一个改写过的地址,
        即在原有地址后追加SessionID,这种重新定义URL内容的方式叫做URL重写。
    --如:原有地址的写法为http://localhost:8080/test/some
        重写后的地址写法为http://localhost:8080/test/some;jsessionid=4E113CB3
    --如果是重定向,使用如下代码代替response.sendRedirect()
        --response.encodeRedirectURL(String url);

########################### 过滤器和监听器 ################################
>>>>>>>>>>>>>>>>>>>>>>>>> 过滤器 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    
--过滤器是Servlet2.3规范之中一种特殊的Web组件,
    可以作为Servlet的辅助性插件存在。
---作用:
    --常用来做项目中的一些共性的需求
    --如:记录日志、过滤敏感词、权限检查
    --过滤器会以极低的耦合度来处理这样的需求
    >>共性的需求:几乎每个请求都要做的事情
1.如何编写过滤器
    1)编写一个实现了Filter接口的类
        --public class CommentFilter implements Filter{}
    2)实现Filter接口的三个方法,过滤逻辑在doFilter方法中实现
        --Filter接口中共定义了三个方法,分别是init,doFilter,destroy方法。
        --init方法在创建Filter时会被调用,且只调用一次,
            一般在该方法中做一些数据的准备工作,可以通过传入的FilterConfig
            参数获取在web.xml文件中配置提供给过滤器的初始参数。
        --destroy方法只有在销毁过滤器对象时被调用一次,用于释放一些资源的操作
        --doFilter方法内编写过滤器的具体处理逻辑,会被多次执行.
            --该方法共有三个参数:
                request、response:请求和响应用于获取数据以及追加数据
                FilterChain:过滤器链,负责多过滤器的传递。
        --执行FilterChain的doFilter会调用后续的过滤器或者servlet。
             --chain.doFilter(request,response)
                 若调用该方法,则请求继续,若不调用,则请求中断
    3)在Web程序中注册过滤器
     <filter>
          <filter-name>guoLv</filter-name>
          <filter-class>web.GuolvFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>guoLv</filter-name>
          <!-- 声明此filter过滤过滤那些请求 -->
          <url-pattern>/*</url-pattern>
      </filter-mapping>
    4)把过滤器和Web应用一起打包部署
        --将编译后的过滤器和其他Web组件类合在一起,
            连同web.xml文件放进应用程序结构中即可。
2.过滤器的执行流程
    (1)客户端发来请求
    (2)进入过滤器的doFilter方法中
    (3)在doFilter方法中执行chain.doFilter()方法,则将控制权交到Servlet.service()方法,
    (4)执行service()方法中的业务逻辑
    (5)业务逻辑执行结束后,回到过滤器的doFilter()方法中,执行chain.doFilter()方法后面的代码
    (6)该部分有代码就会执行,执行结束后,将response对象返回给客户端    
    --过滤器对servlet执行前后都有过滤效果
3.过滤器的优先级
    --优先级是web.xml文件中<filter-mapping>的声明顺序来决定的
4.过滤器的生命周期
    1)启动服务器时,它会创建filter。
    2)关闭服务器时它会销毁filter
    --服务器只启动一次,所以filter是单例的
    --每个filter解决一个业务,他们的调用顺序以配置文件的顺序为准
5.初始化参数
    <filter>
        <filter-name>filter1</filter-name>
        <filter-class>web.CommentFilter1</filter-class>
        <!-- 初始化参数 -->
        <init-param>
          <param-name>illegalStr</param-name>
          <param-value>胡萝卜</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <url-pattern>/comment</url-pattern>
    </filter-mapping>  
6. 读取初始化参数
    private FilterConfig config;    
    public void init(FilterConfig fc) throws ServletException {
        config = fc;
    }
    public void doFilter(ServletRequest req, 
                        ServletResponse res, FilterChain chain) 
                        throws IOException, ServletException {
        String illegalStr = config.getInitParameter("illegalStr");
        // … …
    }
    public void destroy() {// … …}

>>>>>>>>>>>>>>>>>>>>>>>>> 监听器 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    
--servlet规范中定义的一种特殊组件,用来监听servlet容器产生的事件并进行响应的处理。
1.生命周期相关的事件
    容器创建或者销毁request,session,ServletContext时产生的事件。
    --如:统计在线人数
2. 绑定数据相关的事件
    --调用(request,response,ServletContext)三个对象的
        setAttribute,removeAttribute方法时产生的事件。
3.如何编写监听器
    step1:写一个java类,实现相应的监听器接口(共有8个接口)。
        要依据监听的事件类型来选择相应的监听器接口,
        比如要监听session对象的创建和销毁,要实现HttpSessionListener。
    step2:在监听器接口方法中,实现相应的监听处理逻辑。
        比如,session对象被删除了,将人数减1。
    step3:注册(在web.xml文件中配置即可)。
4.编写Java类
    public class CountListener implements HttpSessionListener{
        private int count = 0;
        public void sessionCreated(HttpSessionEvent arg0){
            System.out.println("sessionCreated…");
            count ++;
        }
        public sessionDestroyed(HttpSessionEvent arg0){
            System.out.println("session destroyed…");
            count--;
        }
    }
5.实现处理逻辑
    public void sessionCreated(HttpSessionEvent e){
        System.out.print("sessionCreated…");
        HttpSession session = e.getSession();
        ServletContext ctx = session.getServletContext();
        ctx.setAttribute("count",count);
    }
6.注册监听器
    <listener>
        <listener-class>web.CountListener</listener-class>
    </listener>
7.监听器的应用场景    
    系统框架级别的代码经常需要检测容器中数据或对象的变化,
    以一个不受人为控制因素的触发为执行时机,
    所以对于需要根据数据变化来做出自动反馈的功能都可以使用到监听器.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值