概念
1.运行环境
JDK1.8
Tomcat 8.0
Intellij IDEA : http://www.jetbrains.com/idea/
写一个web项目时还需要一个jar包javax.servlet.-api.jar
要将其复制到JDK的扩展目录中去,角度看。D:jdk1.7/jre/lib/ext
2.工作原理
先附上代码吧嘻嘻嘻
这是web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>servlet1
</servlet-name>
<servlet-class>classes.myservlet.control.servlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
好的,看到这个web.xml文件,我们就先来看看这几个标记代表的意思
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>这里就是我们的servlet文件名
</servlet-name>
<servlet-class>这里时我们的servlet文件所在位置,一般是在项目的src目录下</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>这里也是我们的项目名,一般web.xml中不止配置一个servlet,所以需要靠servlet的名字进行搜索匹配</servlet-name>
<url-pattern>这里是浏览器上搜索需要加上的servlet文件的url片段</url-pattern>
</servlet-mapping>
</web-app>
我们在浏览器上通过主机号和<servlet-mapping>的url片段找到servlet-name
然后通过<servlet>的servlet-name找到具体的servlet.class
这是servlet文件
package classes.myservlet.control;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class servlet1 extends HttpServlet
{
public void init(ServletConfig config)throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request, HttpServletResponse response)throws IOException{
request.setCharacterEncoding("gbk");
String str=request.getParameter("moon");
response.setContentType("text/html;charset=gbk");
PrintWriter out=response.getWriter();
String servletName=getServletName();
out.println("<html><body bgcolor=#eeddff>");
out.println("<b>请求的servlet的名字是"+servletName+"<br></b>");
out.println("<b>servlet在WEB设计中非常重要<br></b>");
if(str!=null&&str.length()>=1)
out.println("<br><h2>"+str+"<h2>");
out.println("</body></html>");
}
}
我这里直接在response写完了页面
用Java写完servlet文件和前端页面之后,配置好web.xml,启动tomcat服务器
在浏览器中用local host:8080(端口号)/页面或servlet名?参数1=value&参数2=value(例如:http://localhost:8080/hello?moon=ajie)
(1)servlet的生命周期
每个servlet文件都要继承HttpServlet
生命周期分为三个过程
初始化Servlet,调用init方法完成必要的初始化工作
新诞生的Servlet调用service方法响应用户请求
当服务器关闭时,调用destroy方法销毁servlet
通过jsp页面访问servlet
jsp的位置
可以在页面中通过用表单的形式向servlet提交数据
<form action="accountBill?side=4&side1=5">
这里的accountBill就是servlet文件,
用这种方法把表单信息传给servlet文件。
这里还传了两个参数值
<input type="submit" value="提交">
form里面需要有一个提交按钮
<form>
还可以用超链接
<a href="accountBill?side=4&side1=5">
再来讲讲共享变量,照例贴代码
package classes.myservlet.control;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class servlet2 extends HttpServlet
{
double sum=0,i=1,j=1;
int number=0;
public void init(ServletConfig config)throws ServletException{
super.init(config);
}
public void service(HttpServletRequest request, HttpServletResponse response)throws IOException{
request.setCharacterEncoding("gbk");
response.setContentType("text/html;charset=gbk");
PrintWriter out=response.getWriter();
String servletName=getServletName();
out.println("<html><body>");
number++;
sum=sum+i/j;
j=j+2;
i=-i;
out.println("servlet:"+getServletName()+"已经被请求了"+number+"次");
out.println("现在的PI值是:");
out.println(4*sum);
out.println("</body></html>");
}
}
从代码里面可以知道,我们把变量sum等设成全局变量,每一次对servlet的访问,都对service方法进行调用,而sum的值的变化永远在上一次被浏览的基础上进行改变。
好的,接下来我们讲一下请求方式,也就是method标记
package classes.myservlet.control;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class servlet1 extends HttpServlet
{
public void init(ServletConfig config)throws ServletException{
super.init(config);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException{
request.setCharacterEncoding("gbk");
String str=request.getParameter("name");
response.setContentType("text/html;charset=gbk");
PrintWriter out=response.getWriter();
String servletName=getServletName();
out.println("<html><body bgcolor=#eeddff>");
out.println("<b>请求的servlet的名字是"+servletName+"<br></b>");
out.println("<b>servlet在WEB设计中非常重要<br></b>");
if(str!=null&&str.length()>=1)
out.println("<br><h2>"+str+"<h2>");
out.println("</body></html>");
}
public void service(HttpServletRequest request, HttpServletResponse response)throws IOException{
request.setCharacterEncoding("gbk");
String str=request.getParameter("name");
response.setContentType("text/html;charset=gbk");
PrintWriter out=response.getWriter();
String servletName=getServletName();
out.println("<html><body bgcolor=#eeddff>");
out.println("<b>请求的servlet的名字是"+servletName+"<br></b>");
out.println("<b>servlet在WEB设计中非常重要<br></b>");
if(str!=null&&str.length()>=1)
out.println("<br><h2>"+str+"<h2>");
out.println("</body></html>");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException{
request.setCharacterEncoding("gbk");
String str=request.getParameter("name");
response.setContentType("text/html;charset=gbk");
PrintWriter out=response.getWriter();
String servletName=getServletName();
out.println("<html><body bgcolor=#eeddff>");
out.println("<b>请求的servlet的名字是"+servletName+"<br></b>");
out.println("<b>servlet在WEB设计中非常重要<br></b>");
if(str!=null&&str.length()>=1)
out.println("<br><h2>"+str+"<h2>");
out.println("</body></html>");
}
}
可以看到,其中有三个方法,doget(),dopost(),service()
<form action="/hello?name=name"method="post">
<input type="text" name="name">
</form>
当我用post方法访问时
当我用get访问时
可以看出,当有service方法时,不管请求方式是post还是get,都直接执行service方法
那么如果没有service方法呢?嗯~~好问题
我们来看看
把代码中的service()方法去掉
用post方法调用
当用get方法调用时
嗯嗯,原来是这样滴,这里有service()方法时,所有通过hello进到servlet.java的都执行service方法,如果没有,再按照method标记的方式去找doGet()或者doPost()方法。
这是我们自己实验得到的结果,那么到底是不是百分之百准确呢?
怎么验证呢,哦吼。
还记不记得servlet的生命周期,小编早就知道你看过就忘了,要好好记得原理的东西。
这张详细的生命周期图收好了
-
init()方法
在Servlet的生命周期中,仅执行一次init()方法,它是在服务器装入Servlet时执行的,可以配置服务器,以在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init();
-
service()方法
它是Servlet的核心,每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。在HttpServlet中已存在Service()方法。默认的服务功能是调用与HTTP请求的方法相应的do功能。
-
destroy()方法
仅执行一次,在服务器端停止且卸载Servlet时执行该方法,有点类似于C++的delete方法。一个Servlet在运行service()方法时可能会产生其他的线程,因此需要确认在调用destroy()方法时,这些线程已经终止或完成。
该去看看源码了。
有心的可以自己找出来看看,自己找总是好的,了解更多,小编给你们的也是小编自己的理解,得到新理解大家可以互相讨论
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
由此可知,如果我们没写service()方法时,它会到我们继承的这个类中找到这个方法,然后去找doGet()等等。
请求方法的问题就说到这,接下来轮到另一个point了。
在过程中我们除了超链接或者提交信息给某个页面,还有另外一个方法,通过转发的方式
这是第一个请求页面
然后就跳到servlet3.java控制跳转
package classes.myservlet.control;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class servlet3 extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String number=request.getParameter("number");
try{
double n=Double.parseDouble(number);
if(n<0)
response.sendRedirect("example5_6.jsp");
else{
RequestDispatcher dispatcher=request.getRequestDispatcher("example5_6.jsp");
dispatcher.forward(request,response);
}
}
catch (NumberFormatException e){
response.sendRedirect("example5_6.jsp");
}
}
}
response.sendRedirect(“要跳转的页面”)
这是重定向,由方法即可看出,是要把页面调用过来而已
RequestDispatcher dispatcher=request.getRequestDispatcher(“要跳转的页面”) ;dispatcher.forward(request,response);
这是转发,由方法可知,它还将request的内容传过去了
对比之后,即见分晓。
说到这里,顺便提一下很少见到的include,这也是request.getRequestDispatcher()的一个方法,与forward不同的是request是将跳转页面的response作为response,而include是将后者作为申请页面response的补充
接下来轮到另外一个重要的概念了
session
许多时候,我们需要服务器为我们保存一个value,所以我们会用到session,可以确保在这个会话中保持不变,除非我们主动更改
照例贴代码讲解
package classes.myservlet.control;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class servlet4 extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
HttpSession session=request.getSession(true);
String str=request.getParameter("clientGuessLetter");
Character guessLetter=str.trim().charAt(0);
Character savedLetter=(Character)session.getAttribute("savedLetter");
char realLetter=savedLetter.charValue();
if(Character.isUpperCase(guessLetter)){
guessLetter=Character.toLowerCase(guessLetter);
}
if(guessLetter<realLetter){
session.setAttribute("message","您猜小了");
response.sendRedirect("example5_7input.jsp");
}
if(guessLetter>realLetter){
session.setAttribute("message","您猜大了");
response.sendRedirect("example5_7input.jsp");
}
if(guessLetter==realLetter){
session.setAttribute("message","您猜对了");
response.sendRedirect("example5_7input.jsp");
}
}
}
<%--
Created by IntelliJ IDEA.
User: 57765
Date: 2019/11/23
Time: 10:04
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body bgcolor="eeffdd">
<%session.setAttribute("message","请您猜字母");
char a[]=new char[26];
int m=0;
for(char c='a';c<='z';c++){
a[m]=c;
m++;
}
int randomIndex=(int)(Math.random()*a.length);
char ch=a[randomIndex];
session.setAttribute("savedLetter",new Character(ch));%>
访问或刷新该页面可以随机得到一个英文字母
<br>单击超链接去猜这个字母:<a href="example5_7input.jsp">去猜字母</a>
</body>
</html>
<%--
Created by IntelliJ IDEA.
User: 57765
Date: 2019/11/23
Time: 10:11
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%String message=(String)session.getAttribute("message");
%>
<table border="1">
<form action="guessLetter" method="post">
<tr>
<td>
输入您的猜测(a~z之间的字母:</td>
</td>
<td>
<input type="text"name="clientGuessLetter" size="4">
<input type="submit" value="提交">
</td>
</tr>
<tr>
<td>
提示信息
</td>
<td>
<%=message%>
</td>
</tr>
</form>
<form action="example5_7.jsp" method="post">
<tr>
<td>
单击按钮重新开始
</td>
<td>
<Input type="submit" value="随机得到一个字母">
</td>
</tr>
</form>
</table>
</body>
</html>
<servlet>
<servlet-name>servlet4
</servlet-name>
<servlet-class>classes.myservlet.control.servlet4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet4</servlet-name>
<url-pattern>/guessLetter</url-pattern>
</servlet-mapping>
可以看到,我们通过进入example5_7.jsp后,得到一个随机英文字母
接着我们就提交进行跳转页面到example5_7input.jsp进行猜字母
在这个过程中,我们没有对session保存的字母进行改变,除非我们按下“重新猜字母”的按钮
session在request.getSession(true)中得到。
嗯~~,好的,算作这两天重新看servlet的总结了,有什么问题可以和小编进行讨论