• JSP webshell免杀——JSP的基础


    唉,每次开启JSP都要好一会儿。

    话说我也不知道为啥,我的每次开启条件一次比一次苛刻。一开始必应就可以打开,再后来只能由谷歌打开,现在可好了得开着代理用谷歌才能进去。

    一个JSP页面可由5种元素组合而成

     (1) 普通的HTML标记和JavaScript标记,CSS。

     (2) JSP标记,如指令标记、动作标记。<%@,<jsp: 

     (3) 变量和方法,类的声明。<%!

     (4) Java 程序片。<% (5) Java 表达式。<%=

    原理 

    ★一个JSP页面被第一次请求执行时,Tomcat服务器首先将JSP页面文件转译成一个Java文件,再将这个Java文件编译生成字节码文件,然后通过执行字节码文件响应用户的请求。

    ★当多个用户请求一个JSP页面时,Tomcat服务器为每个用户启动一个线程,该线程负责执行常驻内存的字节码文件来响应相应用户的请求。这些线程由Tomcat服务器来管理,将CPU的使用权在各个线程之间快速切换,以保证每个线程都有机会执行字节码文件。

    在<%!和%>标记符号之间声明变量,定义方法以及定义类。   <%!和%>标记符号的内容习惯上放在JSP 页面指令之后,<HTML>之前,也可以写在<HTML>与</HTML>之间。

    <%!和%>之间声明的变量在整个JSP页面内都有效,与标记符在JSP页面中所在的书写位置无关,但习惯上把<%!、%> 标记符写在JSP页面的前面。

    <%@ page contentType="text/html" %>   
    <%@ page pageEncoding = "utf-8" %>  
    <HTML><body bgcolor=yellow>
    <%! int i=0;
    %>
    <% i++;
    %>
    <p style="font-family:宋体;font-size:36">
    您是第<%= i %>个访问本站的用户。
    </p>
    </body></HTML>    
     

    <%@ page contentType = "text/html" %>  
    <%@ page pageEncoding = "utf-8" %>  
    <HTML><body bgcolor = #ffccff>
    <p style="font-family:宋体;font-size:36;color:blue">
    <%! double multi(double x,double y){ //定义方法
            return x*y;
        }
        double div(double x,double y) { //定义方法
            return x/y;
        }
        class Circle { //定义类
            double r;
            double getArea(){
               return 3.1415926*r*r;
            }
        }
    %>
    <%  double x=8.79;
        double y=20.8;
        out.print("调用multi方法计算"+x+"与"+y+"之积:<br>");
        out.print(multi(x,y));
        out.print("<br>调用div方法计算"+y+"除以"+x+"的商:<br>");
        String s =String.format("小数点保留3位:%10.3f",div(y,x));
        out.println(s); 
        Circle circle = new Circle(); //用Circle类创建对象。
        circle.r = 3.6;
        out.print("<br>半径是"+circle.r+"的圆面积"+circle.getArea()); 
    %>
    </p></body></HTML>

     可以在<%和%>之间插入Java 程序片。

    ●一个JSP页面可以有许多程序片,这些程序片将被Tomcat服务器按顺序执行。 ●在程序片中声明的变量称作JSP页面的局部变量。局部变量的有效范围与其声明的位置有关,即局部变量在JSP页面后继的所有程序片以及表达式部分内都有效。

    ynchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
    1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
    2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
    3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
    4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
     

    <%@ page contentType = "text/html" %>  
    <%@ page pageEncoding = "utf-8" %>  
    <HTML><body>
    <p style="font-family:宋体;font-size:36;color:blue">
    <%! int count=0;                    //被用户共享的count。
         synchronized void setCount() {  //synchronized修饰的方法。
           count++;
         }
    %>
    <%  setCount();
        out.println("您是第"+count+"个访问本站的客户");   
    %>
    </p></body></HTML>
     

    <%=和%>之间插入一个可求值的表达式(注意:不可插入语句, <%=是一个完整的符号,“<%”和“=”之间不要有空格)。

    ★表达式的值由服务器负责计算,并将计算结果用字符串形式发送到用户端显示。

    ★Java表达式可以写在<HTML>之前,也可以写在<HTML>和</HTML>之间或</HTML>之后。

    <%@ page contentType="text/html" %>  
    <%@ page pageEncoding = "utf-8" %> 
    <HTML><body>
    <p style="font-family:黑体;font-size:22">
      数学,英语和语文成绩单。<br>单科满分是150分。
    </p>
    <% int math = 98;
       int english = 90;
       int chinese = 110;
       int sum = math+english+chinese;
    %>
    <p style="font-family:宋体;font-size:20">
    <table border = 2>
    <tr>
      <td>姓名</td><td>数学成绩</td> <td>英语成绩</td> <td>语文成绩</td> <td>总成绩</td>
    </tr>
    <tr>
      <td>张三</td><td><%= math %></td> <td><%= english %></td> <td><%= chinese %></td>
      <td><%= sum %></td>
    </tr>
    <% math = 115;
       english = 70;
       chinese = 120;
       sum = math+english+chinese;
    %>
    <tr>  
     <td>李四</td><td><%= math %></td> <td><%= english %></td> <td><%= chinese %></td>
     <td><%= sum %></td>
    <tr>
    <% math = 88;
       english = 100;
       chinese = 98;
       sum = math+english+chinese;
    %> 
    <tr> 
     <td>王五</td><td><%= math %></td> <td><%= english %></td> <td><%= chinese %></td>
      <td><%= sum %></td>
    </tr>
    </table>
    </p>
    </body></HTML>
     

     

     注释

    HTML注释:在标记符号“<!--”和“-->”之间加入注释内容:

    <!--    注释内容     -->

    JSP引擎把HTML注释交给用户,因此用户通过浏览器查看JSP页面的源文件时,能够看到HTML注释。

     JSP 注释:在标记符号“<%--”和“--%>”之间加入注释内容:

    <%--  注释内容  --%>

      Tomcat服务器忽略JSP注释,即在编译JSP页面时忽略JSP注释。

    page 指令标记

    page 指令用来定义整个JSP页面的一些属性和这些属性的值。

    <%@ page   属性1="属性1的值"  %>

    <%@ page   属性2="属性2的值"  %> … … <%@ page   属性n="属性n的值"  %>

    也可以用一个page指令指定多个属性的值,如: <%@ page   属性1="属性1的值"  属性2= "属性2的值"  ……%>

    page指令的作用对整个JSP页面有效,与其书写的位置无关。习惯上把page指令写在JSP页面的最前面。

    page 指令标记可以指定属性: contentType、import、language(略)、session(略)、buffer(略)、auotFlush(略) 、isThreadSafe、pageEncoding 、info

    (1)contentType属性

    JSP页面设置响应的MIME(Multipurpose Internet Mail Extention)类型,即设置contentType 属性的值。contentType属性值确定JSP页面响应的MIME类型。属性值的一般形式是: "MIME类型"

    <%@ page contentType="text/html " %>

    浏览器启用HTML解析器来解析执行所接收到的信息。

    如果希望用户的浏览器启用本地的MS-Word应用程序来解析执行收到的信息,就可以如下设置contentType属性的值: <%@ page contentType="application/msword" %>

    可以使用page指令为contentType 属性指定的值有:text/html、text/plain、image/gif、 image/x-xbitmap、image/jpeg、image/pjpeg、application/x-shockwave-flash、application/vnd.ms-powerpoint、 application/vnd.ms-excel、application/msword等

    page指令只能为contentType指定一个值,不允许两次使用page指令给contentType属性指定不同的属性值。

    用page指令为contentType指定一个值的同时,也可以为contentType的附加属性charset指定一个值(默认值是iso-8859-1),例如: <%@ page contentType="text/html;charset=gb2312" %>

    contentType的附加属性charset的值是通知用户浏览器用怎样的编码解析收到的字符, 当JSP页面用page指令指定设置charset的值是gb2312时,浏览器会将编码切换成gb2312。

    但是,如果JSP页面用page指定了JSP的页面本身的编码,例如:<%@ page pageEncoding = "utf-8" %>,那么charset的值和JSP的页面编码保持一致,即也是utf-8(目前的浏览器都支持utf-8编码,所以一般不需要再指定charset的值,使其和JSP的页面编码保持一致即可)

    (2)pageEncoding 属性

    只能为pageEncoding指定一个值,不允许两次使用page指令给pageEncoding属性指定不同的或相同的属性值。

    例如: <%@ page pageEncoding = "utf-8" %> 那么保存JSP页面应当将“编码”选择为“utf-8”

    (3) language属性

    language属性定义JSP页面使用的脚本语言,该属性的值目前只能取"java"。

    为language属性指定值的格式是: <%@ page  language="java" %>

    language属性的默认值是"java",即如果在JSP页面中没有使用page指令指定该属性的值的,那么,JSP页面默认有如下的page指令: <%@ page  language="java" %>

    (4)import 属性

    该属性的作用是为JSP页面引入Java运行环境提供的包中的类。

    <%@ page  import="java.io.*", "java.time.LocalDate" %>

    <%@ page  import="java.util.*" %>

    <%@ page  import="java.io.*"  %>

    JSP页面默认有import属性已经如下的值: " java.lang.*"、 "javax.servlet.*"、"javax.servlet.jsp.*"、"javax.servlet.http.*"。

    (5) session属性

    session 属性用于设置是否需要使用内置的session对象。session的属性值可以是true或false。session属性默认的属性值是true。

    (6)buffer属性

    内置输出流对象out负责将服务器的某些信息或运行结果发送到用户端显示。buffer属性用来指定out设置的缓冲区的大小或不使用缓冲区。

    例如: <%@ page buffer= "24kb" %> buffer属性的默认值是8kb 。

    (7) autoFlush属性

    autoFlush可以取值true或false。autoFlush属性的默认值是true。

    (8)isThreadSafe 属性

    isThreadSafe的属性值可取true或false。

    isThreadSafe属性值为true时,CPU的使用权在各个线程间快速切换.

    isThreadSafe属性值设置成false时,该JSP页面同一时刻只能响应一个用户的请求,其他用户须排队等待。也就是说,CUP要保证一个线程将JSP页面执行完毕才会把CPU使用权切换给其他线程。

    (9)info 属性

    info属性的属性值是一个字符串,其目的是为JSP页面准备一个常用但可能要经常修改的字符串。

    例如, <%@ page info= "we are students" %>

    可以在JSP页面中使用方法:

    getServletInfo(); 获取info属性的属性值。

    include 指令标记

    如果需要在JSP页面内某处整体嵌入一个文件,就可以考虑使用include指令标记,其语法格式如下: <%@ include file= "文件的URL " %>

    ■ 嵌入的文件的编码必须和当前JSP页面一致,比如二者都是utf-8编码。

    ■ 所谓静态嵌入,就是当前JSP页面和嵌入的文件合并成一个新的JSP页面,然后Tomcat服务器再将这个新的JSP页面转译成Java文件。因此,嵌入文件后,必须保证新合并成的JSP页面符合JSP语法规则,即能够成为一个JSP页面文件。

    ■include指令可以实现代码的复用。比如,每个JSP页面上都可能都需要一个导航条,以便用户在各个JSP页面之间方便地切换,那么每个JSP页面都可以使用include指令在页面的适当位置整体嵌入一个相同的文件。

    ■允许被嵌入的文件使用page指令指定contentType属性的值,但指定的值要与嵌入该文件的JSP页面中的page指令指定的contentType属性的值相同。

    include 动作标记语法格式为: <jsp:include page= "文件的URL" /> 或 <jsp:include page= "文件的URL" >    param子标记 </jsp:include>

    nclude动作标记告诉JSP页面动态包含一个文件,即JSP页面运行时才将文件加入。与静态嵌入文件的include指令标记不同,当Tomcat服务器根据JSP页面产生成Java文件时,不把JSP页面中动作指令include所包含的文件与原JSP页面合并为一个新的JSP页面,而是告诉Java解释器,这个文件在JSP运行(Java文件的字节码文件被加载执行)时才包含进来。

    如果包含的文件是普通的文本文件,就将文件的内容发送到用户端,由用户端的浏览器负责显示;如果包含的文件是JSP文件,Tomcat服务器就执行这个文件,然后将执行的结果发送到用户端,并由用户端的浏览器负责显示这些结果。

    param动作标记

    param标记以“名字—值”对的形式为其他标记提供附加信息,它不能独立使用,必须作为jsp:include,jsp:forward的子标记使用。

    <jsp:param  name= "参数"  value= " 参数的值" />

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %>
    <HTML><body  bgcolor=cyan >
    <% double a=6.12,b=7.08,c=9.22;
    %>
    <p style="font-family:宋体;font-size:36">
    <br>加载triangle.jsp计算三边为<%=a%>,<%=b%>,<%=c%>的三角形面积.
       <jsp:include page="/triangle.jsp">//注意放的位置
         <jsp:param name="sideA" value="<%=a%>"/>
         <jsp:param name="sideB" value="<%=b%>"/>
         <jsp:param name="sideC" value="<%=c%>"/>
       </jsp:include>
    </p></body></HTML>

    <%@ page contentType="text/html" %> 
    <%@ page pageEncoding = "utf-8" %>
    <%! public String getArea(double a,double b,double c) {
           if(a+b>c&&a+c>b&&c+b>a) {
               double p=(a+b+c)/2.0;
               double area=Math.sqrt(p*(p-a)*(p-b)*(p-c)) ;
               String result = String.format("%.2f",area);//保留两位小数
               return result;
           }
           else { 
              return(""+a+","+b+","+c+"不能构成一个三角形,无法计算面积");
           }
        }
    %>
    <%   String sideA=request.getParameter("sideA");
         String sideB=request.getParameter("sideB");
         String sideC=request.getParameter("sideC");
         double a=Double.parseDouble(sideA);
         double b=Double.parseDouble(sideB);
         double c=Double.parseDouble(sideC);
    %>
    <p style="font-family:黑体;font-size:36;color:blue">
    <br><b>我是被加载的文件,负责计算三角形的面积<br>
        给我传递的三边是:<%=sideA%>,<%=sideB%>,<%=sideC%></b>
    <br><b><i>三角形的面积(保留2位小数):<%= getArea(a,b,c)%></i></b></i>
    </p>

     forward 动作标记

    <jsp:forward page="要转向的页面" /> 或 <jsp:forward page="要转向的页面" >    param子标记 </jsp:forward>

    指令的作用是:

    从该指令处停止当前页面的执行,而转向执行page属性指定的JSP页面。需要注意的是,当前页面使用forward动作标记转向后,尽管用户看到了转向后的页面的效果,但浏览器地址栏中显示的仍然是转向前的JSP页面的URL地址,因此,栏如果刷新浏览器的显示,将再次执行当前浏览器地址中显示的JSP页面。

    <%@ page contentType="text/html" %>  
    <%@ page pageEncoding = "utf-8" %>  
    <HTML><body>
    <h1> 产生一个1-10之间的随机数
    <%  double i=(int)(Math.random()*10)+1;
        if(i<=5) {
    %>      <jsp:forward page="example2_12_a.jsp" >
                <jsp:param name="number" value="<%= i %>" />
            </jsp:forward> 
    <%  }
        else {
    %>     <jsp:forward page="example2_12_b.jsp" >
               <jsp:param name="number" value="<%= i %>" />
           </jsp:forward> 
    <%  }
    %>
    </body></HTML>
     

    <%@ page contentType="text/html" %>  
    <%@ page pageEncoding = "utf-8" %>  
    <HTML><body bgcolor=cyan>
    <p style="font-family:宋体;font-size:36">
    <% String s=request.getParameter("number");
        out.println("传递过来的值是"+s);
    %>
    <br><img src=/tomcat-power.gif width=300 height=280/>
    </p></body></HTML>

    <%@ page contentType="text/html" %>  
    <%@ page pageEncoding = "utf-8" %>  
    <HTML><body bgcolor=yellow>
    <p style="font-family:宋体;font-size:36">
    <% String s=request.getParameter("number");
        out.println("传递过来的值是"+s);
    %>
    <br><img src=/tomcat.gif width=300 height=280 />
    </p></body></HTML>

    Tag文件

    Tag文件和JSP文件很类似,可以被JSP页面动态加载调用,实现代码的复用(但用户不能通过该Tag文件所在Web服务目录直接访问Tag文件)。 

     Tag文件是扩展名为.tag的文本文件,其结构和JSP文件类似。一个Tag文件中可以有普通的HTML标记符、某些特殊的指令标记(tag) 、成员变量声明和方法的定义、Java程序片和Java表达式。

    Tag标记与Tag文件

    <标记库名:Tag标记 参数。。。 /> 或 <标记库名:Tag标记> 其他内容(称为标体内容)</标记库名:Tag标记>

    一个Tag文件对应着一个Tag标记,把全体Tag标记称之为一个自定义标记库或简称为标记库.

    Tag标记的使用

    JSP页在使用Tag标记来调用一个Tag文件之前,必须首先使用taglib指令标记引入该Web服务目录下的标记库,只有这样,JSP页面才可以使用Tag标记调用相应的Tag文件。

    taglib指令的格式如下:

    <%@ taglib tagdir="标记库的位置" prefix="前缀">

    例如: <%@ taglib tagdir="/WEB-INF/tags" prefix="computer"%> 

    引入标记库后,JSP页面就可以使用带前缀的Tag标记调用相应的Tag文件,其中的前缀由<taglib>指令中的prefix属性指定。例如JSP如下使用Tag标记调用相应的Tag文件: <computer:oddNumberSum />

    Tag标记的运行原理

    Tomcat服务器处理JSP页面中的Tag标记的原理如下:

    (1)如果该Tag标记对应的Tag文件是首次被JSP页面调用,那么Tomcat服务器会将Tag文件转译成一个java文件,并编译这个java文件生成字节码文件,然后执行这个字节码文件(这和执行JSP页面的原理类似)。

    (2)如果该Tag文件已经被转编译为字节码文件,Tomcat服务器将直接执行这个字节码文件。

    (3)如果对Tag文件进行了修改,那么Tomcat服务器会重新将Tag文件转译成一个java文件,并编译这个java文件生成字节码文件,然后执行这个字节码文件。

    类似于JSP文件中的page指令。Tag文件通过使用tag指令可以指定某些属性的值,<%@ tag 属性1="属性值" 属性2="属性值" …属性n="属性值"%> 在一个Tag文件中可以使用多个tag指令,因此我们经常使用多个tag指令为属性指定需要的值: <%@ tag 属性1="属性值"%> <%@ tag 属性2="属性值"%> …… <%@ tag 属性n="属性值"%>

    language属性 。只能取值java,其默认值就是java,没有必要使用tag指令指定language属性的值。

    import属性。import属性的作用是为Tag文件引入包中的类import属性默认已经有如下值:"java.lang.*"、 "javax.servlet.*"、"javax.servlet.jsp.*"、"javax.servlet.http.*"。  

    pageEncoding属性。该属性指定Tag文件的字符编码,其默认值是ISO-8859-1。目前,为了避免显示信息出现乱码现象,Tag文件需要将该属性值设置为utf-8。

    include指令

    Tag文件中也有和JSP文件类似的include指令标记,其使用方法和作用与JSP文件中的include指令标记类似。

    attribute指令

    一个Tag文件允许使用它的JSP页面向该Tag文件传递数据。在Tag文件中通过使用attribute指令让使用它的JSP页面向该Tag文件传递需要的数据。

    <%@ attribute name="对象名字" required="true"|"false" type="对象的类型"%> 例如Tag文件myTag.tag中有如下attribute指令: <%@ attribute name="result" required="true" type="java.lang.Double"%> 那么就相当于Tag文件中有了一个名字是result的对象,但Tag文件不需要创建该对象result,而是等待JSP页面将一个Double型的对象的引用传递给result。

    JSP页面使用Tag标记向所调用的Tag文件中name指定的对象传递一个引用,方式如下: <前缀:Tag文件名字 对象名字="对象的引用" /> 比如,JSP页面使用Tag标记(假设标记的前缀为computer)调用myTag.tag: <computer:myTag  result= "new Double(3.1415926)" />

    variable指令

    Tag文件通过使用variable指令可以将Tag文件中的对象返回给调用该Tag文件的JSP页面。

    <%@ variable name-given=“对象名" variable-class="对象的类型" scope="有效范围"%>

    scope的值可以取:AT_BEGIN、NESTED和AT_END。

    taglib指令

    <%@ taglib tagdir="自定义标记库的位置" prefix="前缀"> 一个Tag文件也可以使用几个taglib指令标记引入若干个标记库,例如: <%@ taglib tagdir="/WEB-INF/tags" prefix="beijing"%> <%@ taglib tagdir="/WEB-INF/tags/tagsTwo" prefix="dalian"%

     JSP 内置对象

    HTTP通信协议是用户与服务器之间一种提交(请求)信息与响应信息(request/response)的通信协议。在JSP中,内置对象request封装了用户提交的信息,那么该对象调用相应的方法可以获取封装的信息,即使用该对象可以获取用户提交的信息。 内置对象request是实现了ServletRequest接口类的一个实例,可以在Tomcat服务器的webapps\tomcat-docs\servletapi中查找ServletRequest接口的方法。

    获取用户提交的信息

    用户通常使用HTML的form表单: <form  action= "请求访问的页面或Servlet"  method= get | post  >     提交内容 </form>

    <form action="tom.jsp" method= "post" >      <input type="text" name="boy" value= "ok" />      <input type="submit" name="submit" value="提交"/> </form>

    获取用户提交的信息

    request对象获取用户提交信息的最常用的方法是getParameter(String s)

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %> 
    <HTML><body bgcolor = #ffccff> 
       <form action="example4_1_computer.jsp" method=post >
           <input type="text" name="sizeA" value=9 size=6 />
           <input type="text" name="sizeB" value=8 size=6 /> 
           <input type="text" name="sizeC" value=8 size=6 />
           <input type="submit" name="submit" value="提交"/>
       </form> 
    </body></HTML>
     

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %> 
    <HTML><body bgcolor = #ccffff>
    <p style="font-family:黑体;font-size:36;color:blue">
    <%  
        String sideA=request.getParameter("sizeA");
        String sideB=request.getParameter("sizeB");
        String sideC=request.getParameter("sizeC");
        try {  double a=Double.parseDouble(sideA);
               double b=Double.parseDouble(sideB);
               double c=Double.parseDouble(sideC);
               double p=(a+b+c)/2,area=0;
               area=Math.sqrt(p*(p-a)*(p-b)*(p-c));
               String result = String.format("%.2f",area);
               out.println("<BR>三边:"+sideA+","+sideB+","+sideC);
               out.println("<BR>三角形面积(保留2位小数):"+result);
        }
        catch(NumberFormatException ee){
              out.println("<BR>请输入数字字符");
        } 
    %>
    </p></body></HTML> 

     

     request对象获取用户提交信息的最常用的方法是getParameter(String s)

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %> 
    <%@ page import="java.util.regex.Pattern" %>
    <%@ page import="java.util.regex.Matcher" %>
    <style>
       #tom{
          font-family:宋体;font-size:22;color:blue 
       }
    </style> 
    <HTML><body id ="tom" bgcolor = #ffccff>
    输入购物小票内容(显示的是默认内容):
    <%
       String content = "牛奶:12.68元,面包:6.6元,"
                        +"苹果:28元,香皂:6.58元";
    %>
    <form  action =""  method="post" id ="tom">
       <textArea  name="shopping" rows=5 cols=32 id ="tom">
          <%= content %>
       </textArea>
       <input type="submit" id ="tom" name="submit" value="提交"/>
    </form>  
    <%   String shoppingReceipt=request.getParameter("shopping");
         if(shoppingReceipt==null) {
            shoppingReceipt="0";
         }
         Pattern pattern;          //模式对象
         Matcher matcher;          //匹配对象
         String regex="-?[0-9][0-9]*[.]?[0-9]*" ;//匹配数字,整数或浮点数的正则表达式。
         pattern = Pattern.compile(regex); //初试化模式对象。
         matcher =
         pattern.matcher(shoppingReceipt); //matcher检索shoppingReceipt。
         double sum = 0;
         while(matcher.find()) {
           String str = matcher.group(); 
           sum += Double.parseDouble(str);
         } 
         out.print("购物小票消费总额:"+sum);
    %>
    </body></HTML>
     

    如果form表单中的action请求的页面是当前页面,可以用双引号""或单引号代替当前页面,即写成action=""或action ='',注意双引号或单引号中不能含有空格。也可省略action参数,即不显式写出action参数。

     String shoppingReceipt=request.getParameter("shopping"); 时得到的shoppingReceipt就是空对象。如果程序使用了空对象,Java解释器就会提示出现了NullPointerException异常。因此,在上述例子2中为了避免在运行时出现NullPointerException异常,使用了如下代码: String shoppingReceipt=request.getParameter("shopping"); if(shoppingReceipt==null) {          shoppingReceipt="0"; }

    处理汉字信息

    用户提交的信息中如果含有汉字字符或其他非ASCII字符的信息,就必须进行特殊的处理方式,防止出乱码现象。

    处理汉字信息 JSP页面文件的编码为utf-8编码。 内置对象request在获取信息之前调用setCharacterEncoding方法设置编码为utf-8(默认是iso-8859-1)就可以避免乱码现象。

    request.setCharacterEncoding("utf-8");

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %> 
    <style>
       #tom{
          font-family:宋体;font-size:26;color:blue 
       }
    </style> 
    <HTML><body id="tom" bgcolor = #ffccff>
    可以输入各种语言的文字,单击提交键:
    <%
       String content = "早上好,Good morning,อรุณสวัสดิ์ค่ะ(泰语),"+
                      " おはよう,Доброе утро,좋은 아침";
    %>
    <form  action="" method='post' >
       <textArea  name="language" id="tom" rows=3 cols=50>
          <%= content %>
       </textArea>
       <input type="submit" id="tom" name="submit" value="提交"/>
    </form>  
    <%   request.setCharacterEncoding("utf-8");
         String variousLanguages=request.getParameter("language");
         out.print(variousLanguages);
    %>
    </p></body></HTML>
     

     request的getParameter方法获取form表单提交的有关信息,但实际上,request对象调用相关方法可以获取请求的许多细节信息。内置对象request常用方法如下:

    1) String getProtocol()  获取用户向服务器提交信息所使用的通信协议,比如http/1.1等。

    2) String getServletPath()  获取用户请求的JSP页面文件的名字(带目录符号\,例如\hello.jsp)。

    3) String getContextPath() 获取用户请求的当前Web服务目录(例如ch4)。

    4) int getContentLength()  获取用户提交的整个信息的长度。

    5) String getMethod()  获取用户提交信息的方式,比如:post或get.

    6) String getRemoteAddr()  获取用户的IP地址。

    7) String getRemoteHost()  获取用户机的名称(如果获取不到,就获取IP地址)。

    8) String getServerName()  获取服务器的名称。

    9) String getServerPort()  获取服务器的端口号。

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %> 
    <HTML><body bgcolor = #ffccff>
    <p style="font-family:宋体;font-size:36;color:blue"> 
       <% request.setCharacterEncoding("utf-8");
          String jsp=request.getServletPath();    //请求的JSP页面
          jsp = jsp.substring(1); //去掉JSP页面名称前面的目录符号/
          String webDir = request.getContextPath();//获取当前Web服务目录的名称
          webDir = webDir.substring(1); //去掉Web服务目录的名称前面的目录符号/
          String  clientIP=request.getRemoteAddr();//用户的IP地址
          int serverPort=request.getServerPort(); // 服务器的端口号
          out.print("<br>shenme:"+request.getServerName());
        %> 
    用户请求的页面:<%= jsp %>
    <br>Web服务目录的名字:<%= webDir %>
    <br>用户的IP地址:<%= clientIP %>
    <br>服务器的端口号:<%= serverPort %>
    </p></body></HTML>

    处理HTML标记(不区分大小写)

    input标记

    <input type="GUI对象" name= "GUI对象的名子" value="GUI中的默认值"/>

    Tom服务器的内置对象request通过name指定的名字来获取GUI对象中提交的数据

    (1)文本框text <input type="text" name="m" value="h" size="8" algin="left" maxlength="9"/> 如果用户没有在text输入任何信息,就单击form表单中的submit提交键,request对象调用getParameter方法将获取由value指定的默认值(text中显示的默认值),如果value未指定任何值,getParameter方法获取的字符串的长度为0,即该字符串为""。

    (2)单选框radio <input type="radio" name="hi" value="男" algin= "top" checked="ok" />男生 <input type="radio" name="hi" value="女" algin= "top"  />女生 其中value指定radio的值,如果几个单选键的name取值相同,那么同一时刻只能有一个被选中。 request对象调用getParameter方法获取被选中的radio中value属性指定的值。checked如果取值是一个非空的字符串,那么该单选框的初始状态就是选中状态。   <input type="radio" name="R" value="on" />打开   <input type="radio" name="R" value="off" checked="default">关闭

     (3)复选框checkbox <input type="checkbox" name= "item" value="A"  algin= "top" checked="ok" />足球 <input type="checkbox" name= "item" value="B"  algin= "top"  />围棋 <input type="checkbox" name= "item" value="C"  algin= "top" checked="ok" />乒乓球 <input type="checkbox" name= "item" value="D"  algin= "top"  />篮球 其中value指定checkbox的值。复选框与单选框的区别就是可以多选,即如果几个checkbox的name取值相同,那么同一时刻可有多个chekbox被选中。这时,request对象需调用getParameterValues方法(不是getParameter方法)获取被选中的多个checkbox中value属性指定的值。checked如果取值是一个非空的字符串,那么该复选框的初始状态就是选中状态。

    (4)口令框password <input type= "password"  name= "me"  size= "12"  maxlength="30" /> 用户在口令框中输入tiger,单击提交键,tiger将被提交给form表单请求的页面,请求的页面的内置对象request调用getParameter方法获取password提交的值tiger(password仅仅起着不让别人偷看的作用,不提供加密措施)。

    (5)隐藏hidden <input type= "hidden"  name="nogui"  value= "hello"  /> 用户单击form表单中的submit提交键,那么form表单所请求的页面的内置对象request调用getParameter方法将获取由value指定的值hello。

    (6)提交键submit 为了能把form表单的数据提交给服务器,一个form表单至少包含一个提交键(可以有多个提交键,见稍后的例子10),例如: <input type= "submit"  name="me"  value="确定"  size="12"  /> 单击提交键后,form表单请求的页面才有机会获取form表单提交的各个数据。

    (7)重置键:reset 重置键将表单中输入的数据清空,以便重新输入数据,例如: <input type="reset" value="重置"/>

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %> 
    <style>
       #tom{
          font-family:宋体;font-size:26;color:blue 
       }
    </style> 
    <HTML><body id="tom" bgcolor = #ffccff>
    <form action="example4_5_receive.jsp" method=post id=tom>
       密码:<input type= "password"  name= "me"  size= "12"  maxlength="30" />

      <br>音乐:
      <input type="radio" name="R" value="on" />打开 
      <input type="radio" name="R" value="off" checked="default">关闭 
    <br>哪些是奥运会项目:<br> 
      <input type="checkbox" name= "item" value="A"  algin= "top"  />足球
      <input type="checkbox" name= "item" value="B"  algin= "top"  />围棋
      <input type="checkbox" name= "item" value="C"  algin= "top"  />乒乓球
      <input type="checkbox" name= "item" value="D"  algin= "top"  />篮球
      <input type="hidden" value="我是球迷,但不会踢球" name="secret"/>
      <br><input type="submit" id="tom" name="submit" value="提交"/>
      <input type="reset" id="tom" value="重置" />
    </form> 
    </body></HTML>
     

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %> 
    <%@ page import  = "java.util.Arrays" %> 
    <%! public boolean isSame(String []a,String [] b){
             Arrays.sort(a); 
             Arrays.sort(a);
             return Arrays.equals(a,b);
        }
    %>
    <HTML><body bgcolor = white >
    <p style="font-family:宋体;font-size:36;color:blue"> 
    <%   String answer[] = {"A","C","D"};
         request.setCharacterEncoding("utf-8");  
         String onOrOff=request.getParameter("R"); //获取radio提交的值
         String secretMess=request.getParameter("secret");//获取hidden提交的值
         String itemName[]=request.getParameterValues("item"); //获取checkbox提交的值
         out.println("<br> 是否打开音乐:"+onOrOff);
         out.println("<br> 您的答案:");
         if(itemName==null) {
              out.print("没给答案");
         } 
         else {
             for(int k=0;k<itemName.length;k++) {
               out.print(" "+itemName[k]);
             }
             if(isSame(itemName,answer)){
               out.print("<br>回答正确。");
             }
         }
         out.println("<br> 提交的隐藏信息:"+secretMess);
         if(onOrOff.equals("on")) {
    %>       <br><embed src="sound/back.mp3" />
    <%   } 
    %>
    </p></body></HTML>
     

     select、option标记(下拉列表或滚动列表)

    Tom服务器的内置对象request通过name指定的名字来获取GUI对象中提交的数据.

    <select  name="myName">   <option  value="item1">文本描述</option>   <option  value="item2">文本描述</option>    … … </select>

     <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %>
    <style>
       #tom{
          font-family:宋体;font-size:26;color:blue 
       }
    </style> 
    <%   String music = request.getParameter("music");
         String pic = request.getParameter("pic");
         String onOrOff=request.getParameter("R"); 
         if(music==null) music = "";
         if(pic==null)   pic = "";
         if(onOrOff==null) onOrOff = "off";
    %>
    <HTML><body id=tom background="image/<%= pic %>" >
    <form action=""  method=post >
       <b>选择音乐:<br>
       <select id=tom name="music" >
          <Option selected value="back1.mp3">绿岛小夜曲</option>
          <Option value="back2.mp3">我是一片云</option>
          <Option value="back3.mp3">红河谷</option>
       </select> 
       <input type="radio" name="R" value="on" />打开 
       <input type="radio" name="R" value="off" />关闭 
       <br><b>选择背景图像:<br>
       <select id=tom name="pic" size = 2>
          <option value="back1.jpg">荷花图</option>
          <option value="back2.jpg">玫瑰图</option>
          <option value="back3.jpg">校园图</option>
       </select> <br> 
       <input id=tom type="submit"  name="submit" value="提交"/>
    </form> 
    <%   if(onOrOff.equals("on")) {
    %>       <br><embed src="sound/<%= music %>" height=50 />
    <%   } 
    %>
    </body></HTML> 

    textArea标记

    Tom服务器的内置对象request通过name指定的名字来获取GUI对象中提交的数据.

    <textArea  name="名字"  rows= "文本可见行数"  cols= "文本可见列数" >   提交或显示的数据 </textArea>

    style样式标记

    style标记可用于定义HTML其他标记中的字体样式,如,style标记给出样式:

    <style>    

    #textStyle{       font-family:宋体;font-size:18;color:blue    }    

    #tom{       font-family:黑体;font-size:16;color:black    }

    </style>

    其中,#字符之后的字符序列是样式名称,例如#textStyle给出的样式名称是textStyle(起一个自己喜欢且容易理解的名字),其它html标记可以让其id属性值是样式名称来使用这个样式。例如,段落标记p就可以如下使用textStyle样式:

    table标记(主要用于显示数据,不能提交数据)

    <table  border ="边框的宽度">    

    <tr  width="该行的宽度">        

    <th  width="单元格的宽度" >单元格中的数据</th>  

           …         <td  width= "单元格的宽度" >单元格中的数据</td> …    

    </tr> … …. </table>

    <%@ page contentType="text/html" %>
    <%@ page pageEncoding = "utf-8" %>
    <style>
       #textStyle{
          font-family:宋体;font-size:28;color:blue 
       }
    </style> 
    <HTML><body id = textStyle bgcolor = #ffccff>  
    <form action="example4_7_showCalendar.jsp" method=post >
    输入日期的年份选择月份查看日历.<br>
    年份:<input type="text" name="year" id = textStyle value=2022 size=12 />
    月份 <select name="month" id = textStyle size =1>
      <option value="1">1月</option>
      <option value="2">2月</option>
      <option value="3">3月</option>
      <option value="4">4月</option>
      <option value="5">5月</option>
      <option value="6">6月</option>
      <option value="7">7月</option>
      <option value="8">8月</option>
      <option value="9">9月</option>
      <option value="10">10月</option>
      <option value="11">11月</option>
      <option value="12">12月</option>
    </select><br>  
    <input type="submit" id = textStyle value="提交"/>
    </form> 
    </body></HTML>

    <%@ page import="java.time.LocalDate" %>
    <%@ page import="java.time.DayOfWeek" %>
    <%
        request.setCharacterEncoding("utf-8");  
        String year=request.getParameter("year"); 
        String month=request.getParameter("month");
        int y = Integer.parseInt(year);
        int m = Integer.parseInt(month);
        LocalDate date = LocalDate.of(y,m,1);
        int days = date.lengthOfMonth(); //得到该月有多少天。
        int space = 0;                   //存放空白字符的个数
        DayOfWeek dayOfWeek = date.getDayOfWeek(); //得到1号是星期几
        switch(dayOfWeek) {
              case SUNDAY:    space = 0;
                              break;
              case MONDAY:    space = 1;
                              break;
              case TUESDAY:   space = 2;
                              break;
              case WEDNESDAY: space = 3;
                              break;
              case THURSDAY:  space = 4;
                              break;
              case FRIDAY:    space = 5;
                              break;
              case SATURDAY:  space = 6;
                              break;
       }
       String [] calendar = new String[space+days]; //用于存放日期和1号前面的空白
       for(int i=0;i<space;i++)
           calendar[i]="--";
       for(int i = space,n=1;i<calendar.length;i++){
           calendar[i] = String.valueOf(n) ;
           n++;
       }  
    %>
    <HTML><body bgcolor = #ffccff>
    <h3> <%=year %>年<%=month %>月的日历:</h3>
    <table  border=0>
      <tr><th>星期日</th><th>星期一</th><th>星期二</th><th>星期三</th>
          <th>星期四</th><th>星期五</th><th>星期六</th>
      </tr>
    <% 
       int n = 0;
       while(n<calendar.length){
           out.print("<tr>");
           int increment = Math.min(7,calendar.length-n);
           for(int i=n;i<n+increment;i++) {
             out.print("<td align= center>"+calendar[i]+"</td>");
           }
           out.print("</tr>");
           n = n+increment;
       }
    %> 
    </table></body></HTML>
     

    <image>标记

    不能用于提交数据,用于显示图像。 <image  src="图像文件的URL" >描述文字</image>

    embed标记

    不能用于提交数据。使用embed标记可以播放音乐和视频,当浏览器执行该标记时,会把浏览器所在机器上的默认播放器嵌入到浏览器中,以便播放音乐或视频文件。embed标记的基本格式为: <embed  src="音乐或视频文件的URL" >描述文字</embed > 或 <embed  src="音乐或视频文件的URL" />

    属性值格式的说明

    许多HTML标记的中都有属性,并指定属性的值,例如: <input type="text" name="testAmount" value=10 /> 中的type,name ,value都是input标记的属性, 属性值可以用双引号括起, 也可以用单引号括起, 或者不用任何符号.      比如type属性的值可以用双引号括起"text",也可以用单引号括起'text'或者不用任何符号text,一个好的习惯是用单引号括起。 例如,下列超链接标记中的href的属性值用单引号括起。 <a href = ’example4_1.jsp’>超链接</a>

    处理超链接

    超链接标记 <a href=链接的页面地址 >文字说明</a> 是一个常用标记。例如: <a href ="example4_9_receive.jsp>购买</a> 用户单击超链接标记的文字说明,可以访问超链接给出的链接页面。

    使用超链接标记时还可以增加参数,以便向所链接的页面传递值,格式如下: <a href=链接的页面地址?参数1=字符串1&参数2=字符串2… >文字说明</a> 例如: <a href ="example4_9_receive.jsp?id=A1001&price=8765">购买</a> 超链接所链接的页面,使用request调用getParameter("参数")获得超链接的参数传递过来的参数的值,即字符串。例如: String idStr = request.getParameter("id"); 需要注意的是,超链接标记向所链接的页面传递的参数的值,即字符串中不允许含有非ASCII字符(例如汉字等)。

    动态响应contentType属性

    ■页面用page指令设置页面的contentType属性的值,那么Tomcat服务器将按着这种属性值作出响应,将页面的静态部分返回给用户,用户浏览器接收到该响应就会使用相应的手段处理所收到的信息。

    ■page指令只能为contentType指定一个值来决定响应的MIME类型,如果想动态的改变这个属性的值来响应用户,就需要使用response对象的setContentType(String s)方法来改变contentType的属性值

    ■当用setContentType(String s)方法动态改变了contentType的属性值,即响应的MIME类型,Tomcat服务器就会按着新的MIME类型将JSP页面的输出结果返回给用户。

    session对象

    Tomcat服务器可以使用内置session对象(会话)记录用户的信息。内置对象session由Tomcat服务器负责创建。

    ■当一个用户首次访问web服务目录中的一个JSP页面时,Tomcat服务器产生一个session对象,这个session对象调用相应的方法可以存储用户在访问该web服务目录中各个页面期间提交的各种信息。

    ■这个session对象被分配了一个String类型的id号,Tomcat服务器同时将这个id号发送到用户端,存放在用户(浏览器)的Cookie中。这样,session对象和用户之间就建立起一一对应的关系,即每个用户都对应着一个session对象(称作用户的会话),不同用户(不同浏览器)的session对象互不相同,具有不同的id号码。

    ■当用户再访问该Web服务目录的其它页面时,Tomcat服务器不再分配给用户的新session对象,而是使用完全相同的一个,直到session对象达到了最大生存时间或用户关闭自己的浏览器或Tomcat服务器关闭,Tomcat服务器将销毁用户的session对象

    ★简单地说,用户(浏览器)在访问一个Web服务目录期间,服务器为该用户分配一个session对象(称作和该用户的会话),服务器可以在各个页面使用这个session记录当前用户的有关信息。而且服务器保证不同用户的session对象互不相同。 注--- 同一个用户在不同的Web服务目录中的session是互不相同的。

    application对象

    1)public void setAttribute(String  key ,Object  obj)。application对象可以调用该方法将参数Object 指定的对象 obj添加到application对象中,并为添加的对象指定了一个索引关键字,如果添加的两个对象的关键字相同,则先前添加对象被清除。

    2)public Object getAttibute(String key)。获取application对象含有的关键字是key的对象。由于任何对象都可以添加到application对象中,因此用该方法取回对象时,应显式转化为原来的类型。

    out对象

    out对象是一个输出流,用来向用户端输出数据。在前面的许多例子里曾多次使用out对象进行数据的输出。out对象可调用如下的方法用于各种数据的输出, 例如: out.print(boolean)或out.println(boolean) 用于输出一个布尔值。 out.print(char) 或out.println(char) 输出一个字符。 out.print(double) 或out.println(double)输出一个双精度的浮点数。 out.print(float) 或out.println(float)用于输出一个单精度的浮点数。 out.print(long) 或out.println(long)输出一个长整型数据。 out.print(String) 或out.println(String)输出一个String对象的字符序列。 方法println和print的区别是:println会向缓存区写入一个换行,而print不写入换行。但是浏览器的显示区域目前不识别println写入的换行,如果希望浏览器显示换行,应当向浏览器写入"<br>"实现换行。

    编写Javabean

    编写Javabean就是编写一个Java的类,所以只要会写类就能编写一个Javabean。这个类创建的一个对象称为一个Javabean,简称bean,分配给bean的变量(成员变量),也称bean的属性。为了能让使用bean的应用程序构建工具(比如Tomcat服务器)使用JSP动作标记知道bean的属性和方法,只须在类的方法命名上遵守以下规则:

    (1)如果类的成员变量,也称bean的属性的名字是xxx,那么为了获取或更改bean的属性的值,类中必须提供两个方法: getXxx(),用来获取属性xxx。 setXxx(),用来修改属性xxx.。 也就是方法的名字用get或set为前缀,后缀是将属性(成员变量)名字的首字母大写的字符序列。

    (2)类中定义的方法的访问权限都必须是public的。

    (3)类中定义的构造方法必须是public、无参数的。

    getProperty动作标记

    使用getProperty动作标记可以获得bean的属性值,并将这个值用串的形式发送给用户的浏览器。 <jsp:getProperty  name="bean的id " property="bean的属性" /> 或 <jsp:getProperty  name="bean的id "  property="bean的属性"> </jsp:getProperty> 其中,name取值是bean的id,用来指定要获取哪个bean的属性的值,property取值是该bean的一个属性的名字。 当JSP页面使用getProperty标记获取属性xxx的值时,必须保证bean有相应的getXxx方法,即对方法的名字的命名有特殊的要求。

    让request调用setCharacterEncoding方法设置编码为utf-8,以避免显示bean的属性值出现乱码现象。

    setProperty动作标记

    (1)将bean属性的值设置为一个表达式的值或字符序列。 <jsp:setProperty name="bean的id " property="bean的属性"                                                                   value= "<%=expression%>"/> <jsp:setProperty name="bean的id " property="bean的属性"                                                                   value= "字符序列" /> value给出的值的类型要和bean的属性的类型一致。

    (2)通过HTTP表单的参数的值来设置bean的相应属性的值。 ● 用form表单的所有参数的值设置bean相对应的属性值的使用格式如下: <jsp:setProperty  name= "bean的id的名字"  property="*" /> 在setProperty标记的上述用法中不具体指定bean属性的值将对应form表单中哪个参数指定的值,系统会自动根据名字进行匹配对应,但要求bean属性的名字必须在form表单中有名称相同的参数名字相对应,Tomcat服务器会自动将参数的字符串值转换为bean相对应的属性的值 ● 用form表单的某个参数的值设置bean的某个属性值的使用格式如下: <jsp:setProperty  name= "bean的名字"  property="属性名"  param= "参数名" /> setProperty标记的上述用法具体指定了bean属性的值将对应表单中哪个参数名(param)指定的值,这种设置bean的属性值的方法,不要求property给出的bean属性的名字和param给出的参数名一致,即不要求bean属性的名字必须和表单中某个参数。

    Java Servlet基础

    有些Web应用可能只需要JSP+Javabean就能设计得很好,但是有些Web应用,就可能需要JSP+Javabean+servlet来完成,即需要服务器再创建一些servlet,配合JSP页面来完成整个Web应用程序的工作。

    Servlet类

    写一个创建servlet的类就是编写一个特殊类的子类,这个特殊的类就是javax.servlet.http包中的HttpServlet类。HttpServlet实现了Servlet接口,实现了响应用户的方法(这些方法将在后续内容中讲述)。HttpServlet的子类被习惯地称作一个Servlet类,这样的类创建的对象习惯地被称作一个servlet。

    编写部署文件web.xml

    ■Servlet类的字节码文件保存到指定的目录后,必须为Tomcat服务器编写一个部署文件,只有这样,Tomcat服务器才会用Servlet类创建servlet对象。

    ■部署文件是一个XML文件,名字必须是web.xml。

    ■web.xml由Tomcat服务器负责管理,Tomcat服务器配有内置的解析器,可以解析XML文件的标记中的数据。

    ■编写的web.xml文件必须保存到Web服务目录的WEB-INF子目录中

    ★Web服务目录的WEB-INF子目录下的web.xml文件负责管理当前Web服务目录下的全部servlet,当该Web服务目录需要提供更多的servlet时,只要在web.xml文件中增加servlet和servlet-mapping子标记即可。

    ★对于webapps下的Web服务目录,如果修改并重新保存web.xml文件,Tomcat服务器就会立刻重新读取web.xml文件,因此,修改web.xml文件不必重新启动Tomcat服务器。但是,如果修改导致web.xml文件出现错误,Tomcat服务器就会关闭当前Web服务目录下的所有servlet的使用权限。所以必须保证web.xml文件正确无误,才能成功启动Tomcat服务器。但是,对于不是webapps下的Web服务目录,如果新建或修改了相应的web.xml文件,需要重新启动Tomcat服务器。

    servlet的创建与运行

    ■用户就可以根据web.xml部署文件来请求Tomcat服务器创建并运行一个servlet

    ■如果Tomcat服务器没有名字为hello的servlet,就会根据web.xml文件中servlet标记的子标记servlet-class指定的Servlet类创建一个名字为hello的servlet。因此,如果名字是hello的servlet被创建之后,又修改Java源文件、编译得到新的Servlet类,并希望Tomcat服务器用新的Servlet类创建servlet,那么就要重新启动Tomcat服务器。根据6.1.2中的web.xml文件,用户需在浏览器输入: http://127.0.0.1:8080/ch6/lookHello 请求Tomcat服务器运行名字是hello的servlet。

     servlet 对象的生命周期

    servlet由Tomcat服务器负责创建并完成初始化工作。当多个用户请求一个servlet时,服务器为每个用户启动一个线程。 一个servlet的生命周期主要有下列三个过程组成: (1) servlet第一次被请求加载时,服务器创建servlet,servlet调用init方法完成必要的初始化工作。 (2) 新诞生的servlet再调用service方法响应用户的请求。 (3) 当服务器关闭时,调用destroy方法销毁servlet。 init方法只被调用一次。当后续的用户请求servlet服务时,Tomcat服务器将启动一个新的线程,在该线程中,servlet调用service方法。也就是说,每个用户的每次请求都导致service方法被调用执行,其执行过程分别运行在不同的线程中。

    init方法

    public void init(ServletConfig  config) throws ServletException servlet第一次被请求加载时,服务器创建一个servlet,这个对象调用init方法完成必要的初始化工作。该方法在执行时,服务器会把一个SevletConfig类型的对象传递给init()方法,这个对象就被保存在servlet中,直到servlet被销毁。

    service方法

    public void service(HttpServletRequest request  HttpServletResponse  response)throw ServletException,IOException Tomcat服务器将两个参数传递给该方法。和init方法不同的是,init方法只被调用一次,而service方法可能被多次的调用。当后续的用户请求该servlet时,Tomcat服务器将启动一个新的线程,在该线程中servlet调用service方法响应用户的请求,调用过程运行在不同的线程中,互不干扰。因此,不同线程的service方法中的局部变量互不干扰,一个线程改变了自己的service方法中局部变量的值不会影响其他线程的service方法中的局部变量。

    destroy方法

    public destroy() 当Tomcat服务器终止服务时,destroy()方法会被执行,销毁servlet.子类可直接继承这个方法,一般不需要重写。

    共享变量

    ■Servlet类是HttpServlet的一个子类,在编写子类时就可以声明某些成员变量,那么,请求servlet的用户将共享该servlet的成员变量。

    ■service方法可能被多次的调用。也就是说,当后续的用户请求该servlet时,Tomcat服务器将启动一个新的线程,在该线程中servlet调用service方法响应用户的请求,即每个用户的请求都导致service方法被调用执行,调用过程运行在不同的线程中,互不干扰。因此,不同线程的service方法中的局部变量互不干扰,一个线程改变了自己的service方法中局部变量的值不会影响其他线程的service方法中的局部变量。

    doGet和doPost方法

    ■HttpServlet类除了init、service、destroy方法外,该类还有两个很重要的方法:doGet和doPost,用来处理用户的请求并作出响应。

    ■实际上HttpServlet类所给出的service方法的功能是检查HTTP请求类型(get、post),并在service方法中根据用户的请求方式,在service方法中对应地再调用doGet或doPost方法。

    ■因此,在编写的Servlet类(HttpServlet类的一个子类)时,也可以不重写service方法来响应用户,直接继承service方法即可。

    ■如果不重写service方法,就需要在Servlet类中重写doPost或doGet方法来响应用户的请求。如果不论用户请求类型是post还是get,Tomcat服务器的处理过程完全相同,那么可以只在doPost方法中编写处理过程,而在doGet方法中再调用doPost方法即可,或只在doGet方法中编写处理过程,而在doPost方法中再调用doGet方法。如果根据请求的类型进行不同的处理,就要在两个方法中编写不同的处理过程(这一点比service方法更为灵活)

    重定向与转发

    重定向的功能是将用户从当前页面或servlet定向到另一个JSP页面或servlet。转发的功能是将用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet。本节学习在Servlet类中使用HttpServletResponse类的sendRedirect重定向方法,以及RequestDispatcher类的forward转发方法,并指出二者的区别。

    sendRedirect方法

    重定向方法void sendRedirect(String location) 将用户重新定向到另一个JSP页面或servlet。重定向方法仅仅是将用户从当前页面或servlet定向到另一个JSP页面或servlet,但不能将用户对当前页面或servlet的请求(HttpServletRequest对象)转发给所定向的资源。即重定向的目标页面或servlet无法使用request获取用户提交的数据。

    执行sendRedirect方法(重定向,也见4.2.3)时,Tomcat服务器还是要把当前的servlet代码执行完毕后才实施重定向(跳转)操作,但Tomcat服务器不再给用户看当前servlet代码的执行效果。如果在执行sendRedirect(URL url)方法后,servlet紧接着执行了return返回语句,那么Tomcat服务器会立刻结束当前servlet的执行。

    forward方法

    ⑴   RequestDispatcher dispatcher =   request.getRequestDispatcher(JSP页面的URL或servlet的url-pattern); 例如: RequestDispatcher dispatcher = request.getRequestDispatcher("target.jsp");

    ⑵ 转发。在步骤(1)中获取的RequestDispatcher对象调用 void forward(ServletRequest request,ServletResponse response)             throws ServletException,ava.io.IOException 方法可以将用户对当前JSP页面或servlet的请求转发给RequestDispatcher对象所指定的JSP页面或servlet,例如: dispatcher.forward (request,response); 把用户对当前JSP页面或servlet的请求转变为对转发到的JSP页面或servlet的请求。

    RequestDispatcher对象可以把用户对当前JSP页面或servlet的请求转发给另一个JSP页面或servlet,而且将用户对当前JSP页面或servlet的请求传递给转发到的JSP页面或servlet。也就是说,当前页面所转发到的标页面或servlet可以使用request获取用户提交的数据。

    二者的区别

    ■转发(forwar)和重定向方法(sendRedirect)不同的是,用户可以看到转发到的JSP页面或servlet的运行效果,但是,在浏览器的地址栏中不能看到forward方法转发到的JSP页面的地址或servlet的地址,用户在浏览器的地址栏中所看到的仍然是当前JSP页面的URL或servlet的url-pattern。如果此时刷新浏览器,那么请求将是当前的JSP页面或servlet。所转发到的标页面或servlet可以使用request获取用户提交的数据。而重定向的目标页面或servlet无法使用request获取用户提交的数据。

    ■另外,当servlet中执行forward方法实施转发操作时,Tomcat会立刻结速当前servlet的执行。而servlet中执行sendRedirect方法(重定向,也见4.2.3)时,Tomcat服务器还是要把当前的servlet代码执行完毕后才实施重定向(跳转)操作,但Tomcat服务器不再给用户看当前servlet代码的执行效果。如果在执行sendRedirect(URL url)方法后,servlet紧接着执行了return返回语句,那么Tomcat服务器会立刻结束当前servlet的执行

  • 相关阅读:
    RadonDB MySQL Kubernetes 2.2.1 发布!
    Android Studio轮播图使用失败怎么办【已解决】
    图片的谱表征
    地球的某一片红薯地中秋圆辉少许《乡村振兴战略下传统村落文化旅游设计》——2023学生旅行季许少辉八月新书想象和世界一样宽广
    【选择题】易错题汇总第二辑
    【无标题】
    Mac配置host
    Activity数据库字段说明
    纸牌博弈问题
    前端周刊第三十二期
  • 原文地址:https://blog.csdn.net/weixin_46601374/article/details/125439209