目录
Java Servlet是一种用于创建动态网络应用程序的Java编程语言。Servlet可以处理来自Web客户端的请求和生成响应。本章中,我们将介绍Java Servlet的基础知识,包括Servlet生命周期、Servlet API、Servlet代码结构、Servlet配置等。
Java Servlet的核心思想是在Tomcat服务器创建响应用户请求的servlet对象,简称servlet。
写一个创建servlet的类就是编写一个特殊类的子类,这个特殊的类就是javax.servlet.http包中的HttpServlet类。HttpServlet的子类被习惯地称作一个Servlet类,这样的类创建的对象习惯地被称作一个servlet。
字节码文件按着类的包名对应的目录路径保存到Web服务目录中特定子目录中。包名moon.sun对应的目录路径是moon\sun,因此,保存到:\WEB-INF\classes\moon\sun。"保存类型"选择为"所有文件",将"编码方式"选择为"ANSI"。 然后用命令行进入moon\sun的父目录classes(不要进入moon或sun目录)编译:
classes> javac -cp servlet-api.jar moon\sun\Example6_1.java
注意:编译时不要忘记使用-cp参数,该参数指定使用非核心类库中的类。本章使用的javax.servlet和javax.servlet.http包中的类不在JDK提供的核心类库中,均在servlet-aoi.jar文档中,因此可以将Tomcat安装目录中的lib子目录中的servlet-aoi.jar文件复制(不要剪切)到\WEB-INF\classes中。
(1)Servlet类的字节码文件保存到指定的目录后,必须为Tomcat服务器编写一个部署文件,只有这样,Tomcat服务器才会用Servlet类创建
(2)部署文件是一个XML文件,名字必须是web.xml。
(3)编写的 web.xml文件必须保存到Web服务目录的WEB-INF子目录中。
根据例子6_1给出的Servlet类,web.xml文件的内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<web-app>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>moon.sun.Example6_1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/lookHello</url-pattern>
</servlet-mapping>
</web-app>
一个XML文件应当以XML声明作为文件的第一行,在其前面不能有空白、其他的处理指令或注释。XML使用UTF-8编码,那么标记以及标记的内容除了可以使用ASCII字符外,还可以使用汉字、日文中的片假名、平假名等字符。
让我们来看看 web.xml的具体作用:
xml必须有一个根标记,web.xml文件的根标记是web-app,开始标签和结束标签之间的内容称作根标记的内容。
web-app根标记里可以有若干个servlet标记(称作根标记的子标记)。servlet标记需要两个子标记:servlet-name和servlet-class,其中servlet-name标记的内容是Tomcat服务器创建的servlet的名字,servlet-class标记的内容告知Tomcat服务器用哪个Servlet类来创建servlet。 web.xml文件可以有若干个servlet标记(一个servlet标记部署一个servlet对象),当要求它们的<servlet-name>子标记的内容互不相同,即服务器可以创建多个servlet,它们的名字必须互不相同。
web.xml文件中出现一个servlet标记就会对应的出现一个或多个servlet-mapping标记,该标记和servlet标记都是根标记的直接子标记。servlet-mapping标记需要两个子标记:servlet-name和url-pattern,其中,servlet-name标记的内容是Tomcat服务器翅膀间的servlet的名字(改名字必须和对应的servlet标记的子标记servlet-那么的内容相同)。url-pattern标记用来指定用户用怎样的URL格式来请求servlet。例如,url-pattern标记的内容是/lookHello,那么用户必须在浏览器的地址栏输入:
http://127.0.0:8080/ch6/lookHello
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服务器
用户就可以根据web.xml部署文件来请求Tomcat服务器创建并运行一个servlet。 如果Tomcat服务器没有名字为hello的servlet,就会根据web.xml文件中servlet标记的子标记servlet-class指定的Servlet类创建一个名字为hello的servlet。因此,如果名字是hello的servlet被创建之后,又修改Java源文件、编译得到新的Servlet类,并希望Tomcat服务器用新的Servlet类创建servlet,那么就要重新启动Tomcat服务器。
在请求一个servlet时,可以在请求的url-pattern中额外加入参数及其值,格式是:
url-pattern?参数1=值&参数2=值…参数n=值
那么被请求的servlet就可以使用request对象获取参数的值,例如:
request.getParameter(参数n)
例子6_2中,用户请求servlet绘制一个椭圆,请求时将椭圆的宽(横轴长)和高(纵轴长)通过参数width和height传递给servlet。
Example6_2.java(负责创建servlet,servlet运行效果如图)
package moon.sun;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.geom.*;
import javax.imageio.ImageIO;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Example6_2 extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException{
request.setCharacterEncoding("utf-8");
double width = Double.parseDouble(request.getParameter("width"));
double height = Double.parseDouble(request.getParameter("height"));
response.setContentType("image/jpeg");
Ellipse2D ellipse=new Ellipse2D.Double(400-width/2,300-height/2,width,height);
BufferedImage image = getImage(ellipse);
try {
OutputStream outClient= response.getOutputStream();//指向用户端的输出流。
boolean boo =ImageIO.write(image,"jpeg",outClient);
}
catch(Exception exp){}
}
BufferedImage getImage(Shape shape){ //得到图形的图像
int width=800, height=600;
BufferedImage image =
new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
Graphics2D g_2d=(Graphics2D)g;
g_2d.setColor(Color.blue);
g_2d.fill(shape);
return image;
}
}
ch6\WEB\INF\下的部署文件web.xml添加如下的servlet和servlet-mapping标记,部署的servlet的名字是lookPic,访问servlet的url-pattern是/lookPic
结果:
servlet由Tomcat服务器负责管理,Tomcat服务器通过读取web.xml,然后创建并运行servlet。
servlet由Tomcat服务器负责创建并完成初始化工作。当多个用户请求一个servlet时,服务器为每个用户启动一个线程。 一个servlet的生命周期主要有下列三个过程组成:
(1) servlet第一次被请求加载时,服务器创建servlet,servlet调用init方法完成必要的初始化工作。
(2) 新诞生的servlet再调用service方法响应用户的请求。
(3) 当服务器关闭时,调用destroy方法销毁servlet。 init方法只被调用一次。当后续的用户请求servlet服务时,Tomcat服务器将启动一个新的线程,在该线程中,servlet调用service方法。也就是说,每个用户的每次请求都导致service方法被调用执行,其执行过程分别运行在不同的线程中。
servlet第一次被请求加载时,服务器创建一个servlet,这个对象调用init方法完成必要的初始化工作。该方法在执行时,服务器会把一个SevletConfig类型的对象传递给init()方法,这个对象就被保存在servlet中,直到servlet被销毁。
该方法是HTTPServlet类中的方法,可以在子类中直接继承该方法或重写这个方法,service方法的声明格式时:
public void service(HttpServletRequest request HttpServletResponse response)throw ServletException,IOException
Tomcat服务器将两个参数传递给该方法。一个是HTTPServletRequest类型的对象,该对象封装了用户的请求信息,另一个时HTTPServletResponse类型的对象,该对象用来响应用户的请求。和init方法不同的是,init方法只被调用一次,而service方法可能被多次的调用。因此,不同线程的service方法中的局部变量互不干扰,一个线程改变了自己的service方法中局部变量的值不会影响其他线程的service方法中的局部变量。
该方法是HTTPServlet类中的方法,子类可直接继承这个方法,一般不需要重写。声明格式为:
public destroy()
当Tomcat服务器终止服务时,destroy()方法会被执行,销毁servlet。
按部署文件web.xml给出的servlet的url-pattern,用户除了可以在浏览器输入url-pattern请求运行一个servlet外,也可以通过JSP页面来请求一个servlet。
如果web.xml文件中给出的servlet的url-pattern是/computeBill,那么form表单中action给出的值就是computeBill : <form action= "computeBill " > </form>
当请求一个servlet时,也可以在请求的url-pattern中额外加入参数及其值,格式是: url-pattern?参数1=值&参数2=值…参数n=值 例如:
<form action= "computeBill?sideA=10.66&sideB=23.9&sideC=897 " >
</form>
通过JSP页面访问servlet的好处是,JSP页面可以负责页面的信息显示,信息的有关处理交给servlet去完成。
JSP页面可以使用超链接去请求某个servlet。如果web.xml文件中给出的请求servlet的url-pattern是/circle,那么超链接标记中href的值是circle(不要写成/circle): <a href="circle"></a>
例子6_4使用超链接请求url-pattern是/circle的servlet,在请求的url-pattern中额外加入参数radius,mess及其值。如果参数mess的值是area,servlet将求半径是radius的圆面积,如果参数mess的值是geometry,servlet将绘制半径是radius的圆的图形。
JSP页面 example6_4.jsp:
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<style>
#textStyle{
font-family:宋体;font-size:36;color:blue
}
</style>
<HTML><body bgcolor=#ffccff>
<% double r = 100.8;
%>
<p id=textStyle>
<a href ="circle?mess=area&radius=<%= r %>">看半径<%=r%>圆的面积。</a><br>
<a href ="circle?mess=geometry&radius=<%=r%>">看半径<%=r%>圆的图形。</a>
</p></body></HTML>
Servlet类 Example6_4_Servlet.java:
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.geom.*;
import javax.imageio.ImageIO;
public class Example6_4_Servlet extends HttpServlet{
HttpServletRequest request;
HttpServletResponse response;
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request,HttpServletResponse response)
throws IOException{
this.request = request;
this.response = response;
request.setCharacterEncoding("utf-8");
String mess = request.getParameter("mess");
String radius = request.getParameter("radius");
if(mess.equals("area")) {
getArea(Double.parseDouble(radius));
}
else if(mess.equals("geometry")){
getGeometry(Double.parseDouble(radius));
}
}
void getArea(double r) throws IOException{
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
double area = Math.PI*r*r;
String result = String.format("%.2f",area);
out.print("<h2>半径"+r+"圆的面积(保留2位小数):<br>");
out.print(result);
out.print("</h2></body></html>");
}
void getGeometry(double r) throws IOException{
response.setContentType("image/jpeg");
Ellipse2D ellipse= new Ellipse2D.Double(30,30,2*r,2*r);
BufferedImage image = getImage(ellipse);
OutputStream outClient= response.getOutputStream();
boolean boo =ImageIO.write(image,"jpeg",outClient);
}
BufferedImage getImage(Shape shape){ //得到图形的图像
int width=800, height=600;
BufferedImage image =
new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
g.fillRect(0, 0, width, height);
Graphics2D g_2d=(Graphics2D)g;
g_2d.setColor(Color.blue);
g_2d.fill(shape);
return image;
}
}
web.xml:
<servlet>
<servlet-name>circle</servlet-name>
<servlet-class>moon.sun.Example6_4_Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>circle</servlet-name>
<url-pattern>/circle</url-pattern>
</servlet-mapping>
运行结果:
注:如果JSP页面,例如example6_4.jsp存放在了Web服务目录的子目录中(例如ch6\subDir中),那么web.xml给出的访问servlet的url-pattern中,必须有一个<url-pattern>含有子目录的名字,例如:
<servlet -mapping>
<servlet -name>circle</servlet -name>
<url -pattern>/surDir/circle</url -pattern>
</servlet -mapping>
(1) Servlet类是HttpServlet的一个子类,在编写子类时就可以声明某些成员变量,那么,请求servlet的用户将共享该servlet的成员变量。
(2)service方法可能被多次的调用。也就是说,当后续的用户请求该servlet时,Tomcat服务器将启动一个新的线程,在该线程中servlet调用service方法响应用户的请求,即每个用户的请求都导致service方法被调用执行,调用过程运行在不同的线程中,互不干扰。因此,不同线程的service方法中的局部变量互不干扰,一个线程改变了自己的service方法中局部变量的值不会影响其他线程的service方法中的局部变量。
(1)HttpServlet类除了init、service、destroy方法外,该类还有两个很重要的方法:doGet和doPost,用来处理用户的请求并作出响应。
(2)实际上HttpServlet类所给出的service方法的功能是检查HTTP请求类型(get、post),并在service方法中根据用户的请求方式,在service方法中对应地再调用doGet或doPost方法。 因此,在编写的Servlet类(HttpServlet类的一个子类)时,也可以不重写service方法来响应用户,直接继承service方法即可。
(3)如果不重写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转发方法,并指出二者的区别。
重定向方法void sendRedirect(String location) 将用户重新定向到另一个JSP页面或servlet。重定向方法仅仅是将用户从当前页面或servlet定向到另一个JSP页面或servlet,但不能将用户对当前页面或servlet的请求(HttpServletRequest对象)转发给所定向的资源。即重定向的目标页面或servlet无法使用request获取用户提交的数据。
当前页面所转发道德JSP页面或servlet可以使用request获取用户提交的顺序,下面是实现转发的步骤。
⑴ 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的执行。
使用转发技术可以让JSP页面和处理数据的servlet解耦,JSP页面只需和处理转发的servlet打交道。有利于Web应用程序的维护。
例子6_6中有3个servlet,其中名字是sort的servlet负责排序数字,名字是sum的servlet负责计算数字的代数和,名字是handleForward的servlet负责转发。用户在exmple6_6.jsp页面提供的form表单的textArea中输入一组数字(例如2,-65,1.618)请求handleForward,如果是单击名字含有sort的提交键, handleForward就将用户的请求转发给sort,如果单击名字含有sum的提交键,handleForward就将用户的请求转发给sum。如果用户没有输入任何数字,handleForward就将用户重定向到exmple6_6.jsp。
JSP页面 example6_7.jsp:
<%@ page contentType="text/html" %>
<%@ page pageEncoding = "utf-8" %>
<style>
#textStyle{
font-family:宋体;font-size:36;color:blue
}
</style>
<HTML><body bgcolor=#ffccff>
<p id=textStyle>
<form action="handleForward" id= textStyle method=post>
输入数字(用逗号空格或其他非数字字符分隔):<br>
<textArea name='digitData' id =textStyle rows=5 cols=30 >
</textArea>
<br><input type=submit id=textStyle name = submit value="提交(排序数字sort)"/>
<br><input type=submit id=textStyle name = submit value="提交(求数字代数和sum)"/>
</form>
</p></body></HTML>
Servlet类 Example6_7_Servlet.java:
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Example6_7_Servlet extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
RequestDispatcher dispatcher = null; //负责转发的对象。
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String mess = request.getParameter("submit");
String digitData = request.getParameter("digitData");
if(digitData == null ||digitData.length()==0) {
response.sendRedirect("example6_7.jsp");//重定向到输入数据页面。
return;
}
if(mess.contains("sort")) {
dispatcher = request.getRequestDispatcher("sort");//转发给负责排序的servlet
dispatcher.forward(request,response);
}
else if(mess.contains("sum")){
dispatcher = request.getRequestDispatcher("sum");//转发给负责排序的servlet
dispatcher.forward(request,response);
}
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doPost(request,response);
}
}
Example6_7_Servlet_Sum.java:
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Example6_7_Servlet_Sum extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
String digitData = request.getParameter("digitData");
double sum = getPriceSum(digitData);
out.println("<html><body bgcolor=cyan>");
out.println("<h1>数字的代数和:"+sum);
out.println("</h1></body></html>");
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doPost(request,response);
}
public double getPriceSum(String input){ // 定义方法
Pattern pattern; //模式对象。
Matcher matcher; //匹配对象。
String regex="-?[0-9][0-9]*[.]?[0-9]*" ;//匹配数字的正则表达式。
pattern = Pattern.compile(regex); //初试化模式对象。
matcher = pattern.matcher(input); //初始化匹配对象,用于检索input。
double sum = 0;
while(matcher.find()) {
String str = matcher.group();
sum += Double.parseDouble(str);
}
return sum;
}
}
Example6_7_Servlet_Sort.java :
package moon.sun;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.TreeSet;
import java.util.Iterator;
public class Example6_7_Servlet_Sort extends HttpServlet{
public void init(ServletConfig config) throws ServletException{
super.init(config);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
TreeSet<Double> treeSet = new TreeSet<Double>();//排序数字。
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
String digitData = request.getParameter("digitData");
sort(digitData,treeSet);
Iterator<Double> iterator =treeSet.iterator();
out.println("<html><body bgcolor=cyan>");
out.println("<h1>排序后的数字:<br>");
while(iterator.hasNext()) {
out.println(iterator.next()+",");
}
out.println("</h1></body></html>");
}
public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException{
doPost(request,response);
}
public void sort(String input,TreeSet<Double> treeSet){
Pattern pattern; //模式对象。
Matcher matcher; //匹配对象。
String regex="-?[0-9][0-9]*[.]?[0-9]*" ;//匹配数字的正则表达式。
pattern = Pattern.compile(regex); //初试化模式对象。
matcher = pattern.matcher(input); //初始化匹配对象,用于检索input。
double sum = 0;
while(matcher.find()) {
String str = matcher.group();
treeSet.add(Double.parseDouble(str));
}
}
}
运行结果:
HTTP通信协议是用户与服务器之间一种请求与响应(request/response)的通信协议,属于无状态协议。所谓无状态是指,当用户(浏览器)发送请求给服务器,Tomcat服务器作出响应后,如果同一个用户再发送请求给Tomcat服务器时,Tomcat服务器并不知道就是刚才的那个用户。简单地说,Tomcat服务器不会记录用户的信息。 用户在访问一个Web服务目录期间,Tomcat服务器为该用户分配一个session对象(称为用户的会话),Tomcat服务器可以在各个页面以及servlet中使用这个session记录用户的有关信息,而且Tomcat服务器保证不同用户的session对象互不相同。有关session对象的原理、常用方法可参见第4章的4.3节。
HttpServletRequest对象request调用getSession方法获取用户的session对象: HttpSession session=request.getSession(true); 访问某个Web服务目录的用户,在不同的servlet中获取的session对象是完全相同的,不同的用户的session对象互不相同。
➢JavaServlet的核心是在服务器端创建响应用户请求的对象,即创建servlet对象。
➢servlet对象第一 次被请求加载时,服务器创建一 -个servlet对象,这个对象调用init方法完成必要的初始化工作。init 方法只被servlet对象调用一次,当后续的客户请求该servlet对象服务时,服务器将启动-个新的线程,在该线程中,servlet对象调用service方法响应客户的请求。每个客户的每次请求都导致service方法被调用执行,调用过程运行在不同的线程中,互不干扰。
➢Servlet类继承的service 方法检查HTTP的请求类型(get、post等),并在service方法中根据用户的请求方式,对应地调用doGet或doPost方法。因此,Servlet类不必重写service方法,直接继承该方法即可。可以在Servlet 类中重写doPost或doGet方法来响应用户的请求。
➢RequestDispatcher对象可以把用户对当前JSP页面或servlet的请求转发给另一个JSP页面或srle,而且将用户对当前JSP页面或serlet的请求和响应传递给转发到的JSP页面或srvle.也就是说,当前页面所要转发到的目标页面或servlet对象可以使用request获取用户提交的数据。
文章浏览阅读4.6k次。很简单,下载证书后导入到受信任根目录证书下载,直接在代理状态浏览器访问burp点击CA就可以下载了 设置该证书全部信任,,switchyomega 设置如下即可 就可以抓https的包了 ...
文章浏览阅读1k次。一、循环赛的种类与特点(一)循环赛的种类循环赛又称循环法。是指参赛队(或个人,下同)之间,都要互相轮流比赛,最后按照各参赛队在全部比赛中的胜负场数、得分多少排定名次的比赛方法。它在对抗性项目比赛中经常被采用。循环赛包括单循环、双循环或分组循环三种。单循环是所有参赛队(人)相互轮赛一次;双循环是所有参赛队(人)相互轮赛二次;分组循环是参赛队(人)较多时,采用种子法,把强队(人)分散在各组,先进行小组..._c语言循环赛互打一场比赛 甲队两胜
文章浏览阅读1.6k次,点赞4次,收藏6次。最后的解决方法“在config--WebMvcConfig中不要继承WebMvcConfigurationSupport,而是实现WebMvcConfigurer接口”,且不要在idea中直接点击浏览器图标打开对应的html页面,要自己在浏览器输入url。在本次debug过程中,更加清楚地明白了,springboot项目启动过程中,只扫描引导类同包或子包下的程序,而在resources目录下的静态资源文件(没放到),需要被映射,才能被扫描到。_springboot项目前端端口号不同怎么办
文章浏览阅读80次。configmap 和secret 都需要提前创建configmap和secret都可以为pod提供挂载和变量的方式变量的方式有envfrom全部变量和valuefrom单个变量的引用configmap和secret 需要和引用的pod或者资源对象在同一个ns下。_configmap @value
文章浏览阅读2.2k次。下午在调试的时候报错数据库连接就报错我就很纳闷后面用原来的代码写发现还是报错System.TypeInitializationException:'The type initializer for 'MySql.Data.MySqlClient.Replication.ReplicationManager' threw an exception.'应该是出在Mysql包上的问题..._system.typeinitializationexception:““mysql.data.mysqlclient.mysqlpoolmanag
文章浏览阅读249次。系统安装Ubuntu Server(可百度)更换软件源打开位置cd /etc/apt/编辑sources.listsudo nano sources.list使用清华的软件源镜像deb https://mirrors.ustc.edu.cn/ubuntu-ports/ focal main restricted universe multiversedeb https://mirrors.ustc.edu.cn/ubuntu-ports/ focal-updates main restricted univ_jeecgboot linux部署
文章浏览阅读8.2k次,点赞20次,收藏59次。快给你的Vue项目添加一个编辑图片组件吧给大家推荐一款功能极其强大的图片编辑插件 tui.image-editor快速体验首选在你的前端项目中安装:npm i tui-image-editor// oryarn add tui-image-editor现在你就去新建一个.vue文件,复制进去下面这段代码:<template> <div id="tui-image-editor"></div></template><scr_vue-image-editor
文章浏览阅读4.8k次。标题Flutter与Android混编在Android与Flutter混编中导入flutter的GetX框架时,配置getPages参数出错,在编译时不报错,但是运行之后,debug模式下出现红底白色的错误,错误显示为 Null check operator used on a null value,看一眼懵了,本地开发版本使用的是flutter2,配置的Getx库也确实在很早的版本中就支持了Null safety ,且配置的getPages为数组并且可为空,按照常理怎么也不可能出现这个错误!尝试的方案_flutter null check operator used on a null value
文章浏览阅读4.4k次。查看WIN10 SDK的版本_win10 sdk 版本好哪里查
文章浏览阅读1.4k次。MFC C++改变控件字体大小颜色的方法_cfont设置字体大小
文章浏览阅读202次。关于requests(网络请求库神器 )库快速上手urllib、urllib2、urllib3、httplib、httplib2 都是和 HTTP 相关的 Python 模块,看名字就觉得很反人类,更糟糕的是这些模块在 Python2 与 Python3 中有很大的差异,如果业务代码要同时兼容 2 和 3,写起来会让人崩溃。好在,还有一个非常惊艳的 HTTP 库叫 requests,它是 ..._requests 在线请求工具
文章浏览阅读2.9k次。1.在代码中注入 EntityManager import javax.persistence.EntityManager;@AutowiredEntityManager entityManager; 2.在方法中具体使用EntityManager public List<DefColumn> findAllColumns(String table) { Query query = entityManager.createNativeQue._springboot 执行自定义sql