Sevlet编程

  对Servlet学的总结

Servlet简介

1.Servlet是什么

  Java Servlet是运行在web服务器或应用服务器上的程序,他是作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。使用Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

  Java Servlet 通常情况下与使用 CGI(Common Gateway Interface,公共网关接口)实现的程序可以达到异曲同工的效果。但是相比于 CGI,Servlet 有以下几点优势:

  • 性能明显更好。
  • Servlet 在 Web 服务器的地址空间内执行。这样它就没有必要再创建一个单独的进程来处理每个客户端请求。
  • Servlet 是独立于平台的,因为它们是用 Java 编写的。
  • 服务器上的 Java 安全管理器执行了一系列限制,以保护服务器计算机上的资源。因此,Servlet 是可信的。
  • Java 类库的全部功能对 Servlet 来说都是可用的。它可以通过 sockets 和 RMI 机制与 applets、数据库或其他软件进行交互。

2.Servlet架构

这个图显示了Servlet在Web应用程序中的位置。

Servlet环境设置

以下两个环境变量配置都必须配置,不然出现闪退!!!

1.java开发工具包

  也就是JDK的环境配置,但是要是用JAVA_HOME的配置方法,详情:java环境变量配置

2.设置Web服务器:tomcat

1.在官网下载tomcat

2.tomcat的环境变量

在系统变量中新建下面两个变量

  • CATALINA_BASE tomcat安装目录

    DiAy7Q.jpg

  • CATALINA_HOME tomcat安装目录

BqK3FO.md.jpg

3.打开CLASSPATH的变量值(如果没有就新建)

在CLASSPATH中加入%CATALINA_HOME%\lib\servlet-api.jar;

DiAs0g.jpg

4.在path变量中添加

%CATALINA_HOME%\lib;%CATALINA_HOME%\bin;

DSxsVU.png

进入tomcat安装目录下的bin目录:

  • 双击startup.bat

    启动成功如下:

  • 在浏览器地址栏中输入http://localhost:8080

  • shutdown.bat 关闭tomcat

如果启动startup是乱码,解决方法:

找到tomcat目录下的conf目录,打开“logging.properties”文件,用记事本打开,找到如下配置项:

java.util.logging.ConsoleHandler.encoding = UTF-8

将 UTF-8 修改为 GBK,修改后的效果为:

java.util.logging.ConsoleHandler.encoding = GBK

保存后,重启tomcat!

3.IDEA配置Tomcat

1.点击Run-Edit Configurations…

DiAtkd.jpg

2.点击左侧“+”,选择Tomcat Server—Local

DiAG0e.jpg

3.在Tomcat Server -> Unnamed -> Server -> Application server项目下,点击 Configuration ,找到本地 Tomcat 服务器,再点击 OK按钮。

DiANtA.md.jpg

Servlet生命周期

它的声明周期可被定义为从创建直到毁灭的过程。以下下是Servlet遵循的过程:

  • Servlet初始化后调用init()方法
  • Servlet调用service()方法来处理客户端请求
  • Servlet销毁前调用destroy()方法
  • 最后,Servlet由JVM的垃圾回收器进行垃圾回收

1.init()方法

只调用一次,一次性初始化。init()方法简单地创建或家在一些数据,这些数据将被用于servlet的整个生命周期。

1
2
3
public void init() throws ServletException{
//初始化代码
}

2.service()方法

web容器调用service()方法来处理浏览器的请求,并把格式化的响应写回浏览器。

1
2
3
4
public void service(ServletRequest request, 
ServletResponse response)
throws ServletException, IOException{
}

service方法适当的时候回调用doGet、doPost、doPut、doDelete方法,只用根据客户端的请求类型来重写doGet和doPost方法。

doGet() 方法

GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。

1
2
3
4
5
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}

doPost() 方法

POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。

1
2
3
4
5
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}

3.destroy()方法

也只调用一次,在servlet生命周期结束的时候被调用。这个方法可以关闭数据库连接、停止后台线程、把cookie列表或点击计数器写到磁盘等。

1
2
3
public void destroy() {
// 终止化代码...
}

4.架构图

下图显示了一个典型的 Servlet 生命周期方案。

  • 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。
  • Servlet 容器在调用 service() 方法之前加载 Servlet。
  • 然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方

Servlet实例

1.如何新建Servlet项目

参考链接:https://www.cnblogs.com/liusong-funtime/p/9144275.html

2.servlet第一个程序

Servlet类:服务HTTP请求并实现javax.servlet.Servlet接口的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

// 扩展 HttpServlet 类
public class HelloWorld extends HttpServlet {

private String message;

public void init() throws ServletException
{
// 执行必需的初始化
message = "Hello World";
}

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置响应内容类型
response.setContentType("text/html");

// 实际的逻辑是在这里
PrintWriter out = response.getWriter();
out.println("<h1>" + message + "</h1>");
}

public void destroy()
{
// 什么也不做
}
}

3.Servlet部署

打开WEB-INF目录下的web.xml,在</web-app>中添加以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
   <!--servlet标签给Tomcat配置Servlet程序-->
<servlet>
<!--类名(必须与servlet-mapping中的servlet-name相同)-->
<servlet-name>HelloWorld</servlet-name>
<!--servlet-class是Servlet程序的全路径(全类名)-->
<servlet-class>HelloWorld</servlet-class>
</servlet>
<!--servlet-mapping标签给servlet程序配置访问地址-->
<servlet-mapping>
<!--servlet-name必须和servlet中的servlet-name相同-->
<servlet-name>HelloWorld</servlet-name>
<!--访问的网址-->
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>

Servlet表单数据

1.GET请求和POST请求

浏览器使用GET方法和POST方法让一些信息从浏览器到web服务器,最终走到后台程序。

1.GET请求

BzyiWt.jpg

头信息 描述
Accept 告诉服务器,客户端可以接受的数据类型
Accept-Language 告诉服务器客户端可以接受的语言类型
User-Agent 浏览器信息
Accept-Encoding 告诉服务器,客户端可以接受的数据编码(压缩)格式
Host 表示请求的服务器ip和端口号
Connection 告诉服务器请求链接如何处置
1
http://www.test.com/hello?key1=value1&key2=value2

GET请求将信息作为URL中的?字符后的字符串进行发送。

GET请求是默认从浏览器向Web服务器传递信息的方法,这些信息使用QUERY_STRING头传递。Servlet使用doGet()方法处理这类请求。

2.POST请求

POST请求是把信息作为单独的消息,消息以标准输出的形式传到后台程序。Servlet使用doPost()方法处理这类请求。

2.使用Servlet读取表单数据

Servlet 处理表单数据,这些数据会根据不同的情况使用不同的方法自动解析:

  • getParameter():您可以调用 request.getParameter() 方法来获取表单参数的值。
  • getParameterValues():如果参数出现一次以上,则调用该方法,并返回多个值,例如复选框。
  • getParameterNames():如果您想要得到当前请求中的所有参数的完整列表,则调用该方法

1.使用URL的Get方法实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Servlet implementation class HelloForm
*/
@WebServlet("/HelloForm")
public class HelloForm extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#HttpServlet()
*/
public HelloForm() {
super();
// TODO Auto-generated constructor stub
}

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String title = "使用 GET 方法读取表单数据";
// 处理中文
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 方法请求的方法
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

之后在web.xml中创建以下条目

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>HelloForm</servlet-name>
<servlet-class>HelloForm</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloForm</servlet-name>
<url-pattern>/TomcatTest/HelloForm</url-pattern>
</servlet-mapping>
</web-app>

2.使用表单的POST方法实例

Servlet客户端HTTP请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/DisplayHeader")

//扩展 HttpServlet 类
public class DisplayHeader extends HttpServlet {

// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");

PrintWriter out = response.getWriter();
String title = "HTTP Header 请求实例";
String docType =
"<!DOCTYPE html> \n";
out.println(docType +
"<html>\n" +
"<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
"<body bgcolor=\"#f0f0f0\">\n" +
"<h1 align=\"center\">" + title + "</h1>\n" +
"<table width=\"100%\" border=\"1\" align=\"center\">\n" +
"<tr bgcolor=\"#949494\">\n" +
"<th>Header 名称</th><th>Header 值</th>\n"+
"</tr>\n");

Enumeration headerNames = request.getHeaderNames();

while(headerNames.hasMoreElements()) {
String paramName = (String)headerNames.nextElement();
out.print("<tr><td>" + paramName + "</td>\n");
String paramValue = request.getHeader(paramName);
out.println("<td> " + paramValue + "</td></tr>\n");
}
out.println("</table>\n</body></html>");
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

web.xml的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>  
<web-app>
<servlet>
<!-- 类名 -->
<servlet-name>DisplayHeader</servlet-name>
<!-- 所在的包 -->
<servlet-class>com.myWeb3.DisplayHeader</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DisplayHeader</servlet-name>
<!-- 访问的网址 -->
<url-pattern>/myWeb3/DisplayHeader</url-pattern>
</servlet-mapping>
</web-app>

Servlet服务器HTTP响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//导入必需的 java 库
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/Refresh")

//扩展 HttpServlet 类
public class Refresh extends HttpServlet {

// 处理 GET 方法请求的方法
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 设置刷新自动加载时间为 5 秒
response.setIntHeader("Refresh", 5);
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");

//使用默认时区和语言环境获得一个日历
Calendar cale = Calendar.getInstance();
//将Calendar类型转换成Date类型
Date tasktime=cale.getTime();
//设置日期输出的格式
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//格式化输出
String nowTime = df.format(tasktime);
PrintWriter out = response.getWriter();
String title = "自动刷新 Header 设置";
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" +
"<p>当前时间是:" + nowTime + "</p>\n");
}
// 处理 POST 方法请求的方法
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

HTTP状态码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class showError extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(407,"显示错误");
}

public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException,IOException{
doGet(request,response);
}
}

Servlet编写过滤器

1.什么是过滤器

实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理通常都是用来拦截request进行处理的,也可以对返回地response进行拦截处理。

2.Servlet过滤器的方法

序号 方法 & 描述
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过滤器占用的资源。

idea中创建过滤器后的默认代码:CharsetFilter实现了Filter接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "CharsetFilter")
public class CharsetFilter implements Filter {

/*初始化方法 接收一个FilterConfig类型的参数 该参数是对Filter的一些配置*/
public void init(FilterConfig config) throws ServletException {

//获取的是web.xml中配置Filter时设置的值,参数为设置值的名称,若值不存在,则返回空
String initParam = config.getInitParameter("param");
}

/*过滤方法 主要是对request和response进行一些处理,然后交给下一个过滤器或Servlet处理*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
chain.doFilter(req, resp);//交给下一个过滤器或servlet处理
}
public void destroy() {
/*销毁时调用*/
}
}

web.xml配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<filter>
<filter-name>类名</filter-name>
<filter-class>全类名</filter-class>
<init-param><!-- 设置在过滤器中执行初始化方法时,获取的值,如:param -->
<param-name>param</param-name>
<param-value>studyFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>类名</filter-name>
<!-- 设置为访问该网站所有地址都需要通过该过滤器 -->
<url-pattern>/*</url-pattern>
<!-- 设置为只有访问该网站的/Helloword地址时才通过该过滤器
<url-pattern>/Helloword</url-pattern> -->
</filter-mapping>

3.Servlet过滤器的应用顺序

假设定义了两个过滤器 AuthenFilter 和 LogFilter。需要创建一个如下所述的不同的映射,其余的处理与上述所讲解的大致相同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.runoob.test.LogFilter</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>Initialization Paramter</param-value>
</init-param>
</filter>

<filter>
<filter-name>AuthenFilter</filter-name>
<filter-class>com.runoob.test.AuthenFilter</filter-class>
<init-param>
<param-name>test-param</param-name>
<param-value>Initialization Paramter</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>AuthenFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

web.xml文件中的filter-mapping元素的顺序决定了Web容器应用过滤器到Servlet的顺序。

Servlet Cookie处理

Servlet Session跟踪