当前位置:网站首页>JSP webshell免杀——JSP的基础
JSP webshell免杀——JSP的基础
2022-07-02 07:02:00 【正在过坎】
唉,每次开启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的执行
边栏推荐
- [Fantasy 4] introduction and use of UMG components (under update...)
- VSCode工具使用
- 【MySQL】连接MySQL时出现异常:Connection must be valid and open
- Pywin32 opens the specified window
- 2021-10-02
- 13. Semaphore critical zone protection
- Flutter——Canvas自定义曲线图
- Considerations for Apache deploying static web page projects
- JS reduce accumulator
- 2021-10-04
猜你喜欢
[visual studio] every time you open a script of unity3d, a new vs2017 will be automatically reopened
Webui automated learning
Flutter环境配置保姆级教程,让doctor一绿到底
MYSQL环境配置
Operator-1初识Operator
MongoDB-快速上手MongoDB命令行的一些简单操作
Rapid prototyping
[visual studio] visual studio 2019 community version cmake development environment installation (download | install relevant components | create compilation execution project | error handling)
快速做出原型
14.信号量的代码实现
随机推荐
VLAN experiment
js promise.all
2.hacking-lab脚本关[详细writeup]
【Visual Studio】每次打开一个Unity3D的脚本,都会自动重新打开一个新的VS2017
网络通信学习
Sus system availability scale
01-spooldir
2021-10-02
Redis set password
axis设备的rtsp setup头中的url不能带参
Shapiro Wilk normal analysis by SPSS
[unity3d] nested use layout group to make scroll view with dynamic sub object height
01 install virtual machine
Sum the two numbers to find the target value
Beautiful and intelligent, Haval H6 supreme+ makes Yuanxiao travel safer
【教程】如何让VisualStudio的HelpViewer帮助文档独立运行
Flutter——Canvas自定义曲线图
从MediaRecord录像中读取H264参数
PCL Eigen介绍及简单使用
12. Process synchronization and semaphore