Servlet 教程 | 菜鸟教程 (runoob.com)
目录结构(页面内跳转,暂时没有成功)
[2.5.1、Servlet 3.0](#2.5.1、Servlet 3.0)
Servlet
- Servlet(Server applet):运行在服务器上的小程序;
- 作为一个中间层。在Web浏览器(或其他HTTP客户端的请求),和HTTP服务器上的数据库(或者应用程序)之间;
- 使用Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页;
一、Servlet架构
HTTP Protocol:HTTP 协议;
1.1、Servlet任务
- 读取客户端(浏览器)发送的显式数据,包括网页HTML表单,或者是来自applet或者自定义的HTTP客户端程序的表单;
- 读取客户端(浏览器)发送的隐式的HTTP请求数据,包括cookies、媒体类型和浏览器能理解的压缩格式等;
- 处理数据并生成结果。==这个过程可能需要访问数据库,==执行 RMI 或 CORBA 调用,调用 Web 服务,或者直接计算得出对应的响应。
- 发送显式的数据(即文档)到客户端(浏览器)。该文档的格式可以是多种多样的,包括文本文件(HTML 或 XML)、二进制文件(GIF 图像)、Excel 等。
- 发送隐式的 HTTP 响应到客户端(浏览器)。这包括告诉浏览器或其他客户端被返回的文档类型(例如 HTML),设置 cookies 和缓存参数,以及其他类似的任务。
1.2、Servlet架构
GenericServlet ---- 抽象类继承Servlet
HttpServlet ----抽象类,继承GenericServlet
GenericServlet:将Servlet接口中其他的方法做了默认空实现,只将service()方法作为抽象;
- 将来定义Servlet类时,可以继承GenericServlet,实现service()即可;
HttpServlet:对Http协议的一种封装,简化操作;
- 定义类继承HttpServlet
- 只需要重写doGet以及doPost之类
二、Servlet生命周期
Servlet生命周期从创建到销毁;
- Servlet初始化后调用 init() 方法;
- Servlet调用 service() 方法来处理客户端的请求;
- Servlet销毁前调用 destory() 方法;
- 最后,Servlet是由JVM的垃圾回收器进行垃圾回收。
2.1、生命周期架构图
- 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。
- Servlet 容器在调用 service() 方法之前加载 Servlet。
- 然后Servlet 容器处理由多个线程产生的多个请求, 每个线程执行一个单一的 Servlet 实例的 service() 方法
2.2、init()
init()----初始化方法。在Servlet被创建时,执行init(),而且只会执行一次;
2.2.1、Servlet什么时候被创建?
-
默认情况下,第一次被访问时,Servlet被创建;
-
可以配置执行Servlet的创建时机;
- 在第一次被访问时,创建Servlet;
- 注意:的值为负数;
- 在服务器启动时,创建Servlet;
- 的值为0或正整数;
- 在第一次被访问时,创建Servlet;
<!--配置Servlet-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet全路径</servlet-class>
<!--指定Servlet的创建时机-->
<load-on-start>5</load-on-start>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
2.2.2、Servlet是单例的
- Servlet的init方法只执行一次,这个说明 一个Servlet在内存中只存在一个对象,即Servlet是单例的;
- 注意:如果多个用户同时访问,那么可能存在线程安全问题;
- 如果加上锁的话,会影响到效率问题;
- 解决方法:尽量不要再Servlet中定义成员变量;即使定义了成员变量,也不要对其修改值操作;
public class HelloServlet implements Servlet {
private int age = 3;
// 定义了成员变量,但是不要修改
/*
初始化方法
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init....");
}
/*
获取Servlet的配置对象
*/
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest request,ServletResponse response) throws ServletException {
}
/*
获取Servlet的信息
*/
@Override
public String getServletInfo() {
}
/*
Servlet销毁方法
*/
@Override
public void destory() {
}
}
2.3、service()
-
service()方法是执行实际任务的主要方法。
-
注意:每次服务器接收到一个Servlet请求时,服务器会产生一个新的线程并调用服务。
-
Servlet中所有的service()都做的事情包括:
-
获取请求方式;
-
获取数据;
-
String method = req.getMethod(); if("GET".equals(method)) { // get方式获取数据 }else if("POST".equals(method)) { // post方式获取数据 }
-
当SUN公司发布HttpServlet类的时候,封装doGet、doPost等方法。service()方法直接调用doGet()方法等;
String method = req.getMethod();
if("GET".equals(method)) {
// get方式获取数据
doGet();
}else if("POST".equals(method)) {
// post方式获取数据
doPost();
}
只需要对doGet()以及doPost()等方法重写即可,而且doGet()以及doPost()是每次服务请求 中最常用的方法。
2.3.1、doGet()
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
2.3.2、doPost()
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
2.4、destory()
- 服务器正常关闭时执行destory(),而且只会执行一次;
- 注意:只有服务器正常关闭,才会执行destory();
- destory() 一般在Servlet销毁之前,执行方法以释放资源(让Servlet关闭数据库连接、停止后台线程、把cookie列表或点击计数器写入到磁盘中);
- 在调用destory()方法之后,servlet对象则会被标记为垃圾回收。
2.5、Servlet映射
通常在使用Servlet的时候,都会在web.xml中编写Servlet映射;
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>HelloForm</servlet-name>
<servlet-class>com.runoob.test.HelloForm</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloForm</servlet-name>
<url-pattern>/HelloForm</url-pattern>
</servlet-mapping>
</web-app>
但是在Servlet 3.0版本中,使用注解方式来代替web.xml中繁琐的配置;
@WebServlet(urlPatterns = "/HelloServlet")
public class HelloServlet3 implements Servlet {
}
2.5.1、Servlet 3.0
- 之前的Servlet版本中,一个项目需要编写很多的Servlet。相应的在web.xml中也要编写很多,而Servlet 3.0版本支持注解配置,可以不再需要web.xml。
- JDK 6之后都支持Servlet 3.0;
@WebServlet(urlPatterns = "/HelloServlet")
public class HelloServlet3 implements Servlet {
}
urlPattern:Servlet访问路径
- 一个Servlet可以定义多个访问路径:@WebServlet({“/d1”,“/d2”})
- 路径定义规则
- /xxx(单层路径)
- /xxx/xxx(多层路径):目录结构
- *.do (不能加上/)
- 注意:如果是通配符==*==,那么任何字符都可以;
- 但是通配符的优先级最低(如果通配符遇到其他的路径,那么其他项目执行)
// 定义多个urlPattern
@WebServlet({"/d1","/d2"})
public class HelloServlet3 extends HttpServlet {
}
// 定义多层路径
@WebServlet("/user/demo")
public class HelloServlet4 extends HttpServlet {
}
@WebServlet("/user/*")
public class HelloServlet4 extends HttpServlet {
}
2.6、Servlet实例(需要再编写)
实例:HelloWorld
// 导入必要的Java类库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
private String message;
// Servlet初始化
public void init() throws ServletException {
// 给message赋值
message = "hello world";
}
/*
service()方法由容器调用(Tomcat之类);
只需要编写doGet之类的方法,
再由service() 调用doGet()等
*/
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException {
// 1、设置响应内容类型
response.setContentType("text/html");
// 2、实际业务逻辑
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");
}
// 3、开始销毁Servlet对象,断开数据库连接
public void destory() {
}
}
编写HelloServlet的映射
<!--注册Servlet-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloWorld全路径</servlet-class>
</servlet>
<!--Servlet的请求路径-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<urlPattern>/hello</urlPattern>
</servlet-mapping>
注意:目前在Servlet 3.0以上版本中,映射可以直接使用注解来代替web.xml中的代码;
三、Servlet获取表单数据
前端页面传递信息到后端服务器(浏览器传递信息到web服务器),最常用的包括 post,以及 get;
3.1、GET以及POST区别
GET方法:
-
默认的浏览器向服务器传递信息的方法;
-
效率快,安全性低;
-
请求url中最多只能有1024个字符;
-
页面和已编码的信息中间用 ==?==字符分隔;
-
http://www.test.com/hello?key1=value1&key2=value2
-
-
Servlet采用doGet()方法处理get请求;
POST方法:
- 安全性高,效率较低;
- 请求url中没有字符限制;
- 把信息作为单独的消息,标准输出到后台;
- Servlet采用doPost()方法处理post请求;
3.2、Servlet读取表单数据
Servlet处理表单数据,这些数据会根据不同的情况使用不同的方法来自动解析;
序号 | 方法 | 方法描述 |
---|---|---|
1 | getParameter() | 调用request.getParameter()方法来获取表单参数的值 |
2 | getParameterValues() | 如果出现多个参数,则调用该参数,并返回多个值;例如:复选框 |
3 | getParameterNames() | 如果想要得到当前请求中的所有参数的完整列表,则调用该方法 |
3.3、使用url的GET方法实例
3.3.1、后台程序
@WebServlet("/HelloServlet")
public class HelloServlet extends HelloServlet {
private static final long serialVersionUID = 1L;
public HelloServlet(){
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException {
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWeiter out = response.getWriter();
// 处理中文
String name = new String(
request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");
String docType = "<!DOCTYPE html> \n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body bgcolor=\"#f0f0f0\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n" +
"<ul>\n" +
" <li><b>站点名</b>:"
+ name + "\n" +
" <li><b>网址</b>:"
+ request.getParameter("url") + "\n" +
"</ul>\n" +
"</body></html>");
}
// 处理post请求的方法
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException {
doGet(request,response);
}
}
3.3.2、web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet全路径</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
3.4、使用表单的GET方法实例
前端表单页面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<form action="HelloServlet" method="GET">
网址名:<input type="text" name="name"><br/>
网址:<input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>
之后主程序以及web.xml 一样
3.5、使用表单的POST方法实例
前端表单页面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<form action="HelloServlet" method="POST">
网址名:<input type="text" name="name"><br/>
网址:<input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>
主程序以及web.xml一样
3.6、将复选框数据传递到Servlet程序
前端表单页面
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<form action="CheckBox" method="POST" target="_blank">
<input type="checkbox" name="runoob" checked="checked" /> 菜鸟教程
<input type="checkbox" name="google" /> Google
<input type="checkbox" name="taobao" checked="checked" /> 淘宝
<input type="submit" value="选择站点" />
</form>
</body>
</html>
后端主程序
@WebServlet("/CheckBox")
public class CheckBox extends HttpServlet {
private static final long servialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException {
// 设置响应内容
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String docType = "<!DOCTYPE html> \n";
out.println(docType +
"<html>\n" +
"<head><title>" + title + "</title></head>\n" +
"<body bgcolor=\"#f0f0f0\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n" +
"<ul>\n" +
" <li><b>菜鸟按教程标识:</b>: "
+ request.getParameter("runoob") + "\n" +
" <li><b>Google 标识:</b>: "
+ request.getParameter("google") + "\n" +
" <li><b>淘宝标识:</b>: "
+ request.getParameter("taobao") + "\n" +
"</ul>\n" +
"</body></html>");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,IOException {
doGet(request,response);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>CheckBox</servlet-name>
<servlet-class>com.runoob.test.CheckBox</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CheckBox</servlet-name>
<url-pattern>/TomcatTest/CheckBox</url-pattern>
</servlet-mapping>
</web-app>
四、HTTP请求以及响应
五、Servlet过滤器
- Servlet 过滤器可以动态地拦截请求和响应,并对请求和响应进行处理;
- 注意:可以将一个或多个Servlet过滤器附加到一个Servlet或一组Servlet,Servlet过滤器也可以附加到 JavaServer Pages(JSP)文件和HTML页面。
- 调用Servlet前,就会调用附加的Servlet过滤器;
5.1、常见的Servlet过滤器
- 身份验证过滤器(Authentication Filters)。
- 数据压缩过滤器(Data compression Filters)。
- 加密过滤器(Encryption Filters)。
- 触发资源访问事件过滤器。
- 图像转换过滤器(Image Conversion Filters)。
- 日志记录和审核过滤器(Logging and Auditing Filters)。
- MIME-TYPE 链过滤器(MIME-TYPE Chain Filters)。
- 标记化过滤器(Tokenizing Filters)。
- XSL/T 过滤器(XSL/T Filters),转换 XML 内容。
5.2、Servlet过滤器方法
- 注意:过滤器实现了javax.servlet.Filter接口的Java类。
- Javax.servlet.Filter接口定义了三个接口方法
序号 | 方法 | 描述 |
---|---|---|
1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) | 该方法完成实际的过滤操作,当客户端请求方法与过滤器设置匹配的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain用户访问后续过滤器。 |
2 | public void init(FilterConfig filterConfig) | web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。 |
3 | public void destroy() | Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源。 |
六、Servlet异常处理
当一个Servlet抛出异常的时候,会在web.xml中使用error-page元素来指定对==特定异常或HTTP 状态码== 做出相应的Servlet调用(调用处理页面);
6.1、web.xml配置
<!-- servlet 定义 -->
<servlet>
<servlet-name>ErrorHandler</servlet-name>
<servlet-class>ErrorHandler</servlet-class>
</servlet>
<!-- servlet 映射 -->
<servlet-mapping>
<servlet-name>ErrorHandler</servlet-name>
<url-pattern>/ErrorHandler</url-pattern>
</servlet-mapping>
<!-- error-code 相关的错误页面 -->
<error-page>
<error-code>404</error-code>
<location>/ErrorHandler</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/ErrorHandler</location>
</error-page>
<!-- exception-type 相关的错误页面 -->
<error-page>
<exception-type>
javax.servlet.ServletException
</exception-type >
<location>/ErrorHandler</location>
</error-page>
<error-page>
<exception-type>java.io.IOException</exception-type >
<location>/ErrorHandler</location>
</error-page>
七、Cookie以及Session
-
Cookie是存储在客户端计算机上的文本文件,保留各种跟踪信息;
-
Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。Java Servlet 显然支持 HTTP Cookie。
识别返回用户包括三个步骤:
- 服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。
- 浏览器将这些信息存储在本地计算机上,以备将来使用。
- 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。
7.1、Cookie解析
-page>
403
/ErrorHandler
七、Cookie以及Session
-
Cookie是存储在客户端计算机上的文本文件,保留各种跟踪信息;
-
Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。Java Servlet 显然支持 HTTP Cookie。
识别返回用户包括三个步骤:
- 服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。
- 浏览器将这些信息存储在本地计算机上,以备将来使用。
- 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。