1. Servlet

1.1 基本流程

1
2
3
4
5
6
7
 (*)-> "login.html"
-right-> "form表单处理给 '/login' "
-down-> "web.xml映射,给LoginServlet处理"
-right-> "LoginServlet处理"
-right-> "实例化Servelt"
-up-> "重写 doGet,doPost等方法,获取参数,设置响应"
-up-> "返回html"

web.xml

1
2
3
4
5
6
7
8
9
10
11
<!--注册servlet name-->
<servlet>
<servlet-name>HelloServlet</servlet-name> <!--类的位置-->
<servlet-class>HelloServlet</servlet-class>
</servlet>

<!--设置/hello 映射给HelloServlet-->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
  • 主要实现了处理映射(servlet-mapping标签) 和注册Servlet(servlet标签)

loginServlet

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
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

System.out.println("3. ========== service ============= 函数");

/**
* 中文乱码,设置编码
*/
request.setCharacterEncoding("UTF-8"); //request(请求) 编码
response.setContentType("text/html;charset=UTF-8"); //response(响应) 编码

String name = request.getParameter("name");
String password = request.getParameter("password");

if (name.equals("admin") && password.equals("admin")) { //密码正确
/**
* 服务器内跳转
*/
request.getRequestDispatcher("success.html").forward(request, response);
} else { //密码错误
/**
* 客户端中跳转
*/
response.sendRedirect("fail.html");
}
}
  • service将请求类型分发给doPost, doGet 等方法,用户只用重写这些方法
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
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
*Servlet 的 service 源码
*/
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

String method = req.getMethod();

if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}

} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);

} else if (method.equals(METHOD_POST)) {
doPost(req, resp);

} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);

} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);

} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);

} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);

} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//

String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);

resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}

servlet 跳转

  1. 服务端跳转
    1
    request.getRequestDispatcher("success.html").forward(request, response);
  • 流程如下
    1
    2
    3
    4
    @startuml
    浏览器 -> Tomcat : <color:#0867ff> /login</color>
    Tomcat -> 浏览器 : <color:#0867ff>把success.html的内容发送给浏览器
    @enduml
  1. 客户端跳转
    1
    response.sendRedirect("fail.html");
  • 流程如下
    1
    2
    3
    4
    5
    6
    @startuml
    浏览器 -> Tomcat : <color: #0867ff> /login</color>
    Tomcat -> 浏览器 : <color: #0867ff>服务器发送一条特殊信息给浏览器让浏览器访问fail.html</color>
    浏览器 -> Tomcat : <color: #0867ff> 访问Tomcat</color>
    Tomcat -> 浏览器: <color: #0867ff> 服务端获取fail.html的内容,发送给浏览器</color>
    @enduml

1.2 生命周期

a. 实例化

1
2
3
4
5
6
7
8
9
/**
* 构造方法
* Servlet 是单实例的
* 无论被网页引用多少次,都只被调用一次
*/
public LoginServlet() {
System.out.println("1. ============ 构造 ========= 函数");
System.out.println("LoginServlet 构造方法 被调用");
}

b. 初始化

1
2
3
4
5
6
7
8
9
10
11
/**
* 初始化 init
*
* @param config
*/
@Override
public void init(ServletConfig config) {
System.out.println("2. ============ init ========= 函数");
System.out.println("初始化函数");
System.out.println("init(ServletConfig)");
}

c. 提供服务

  • service -> doGet or service -> doPost

d. 销毁

1
2
3
4
5
6
7
8
/**
* 销毁
*/
@Override
public void destroy() {
System.out.println("4. ============= destroy ============ 函数");
System.out.println("destroy 执行");
}

e. 被回收

1.3 自启动

  • 如果tomcat启动就需要执行一些初始化代码,就需要自启动,如校验数据库完整性

  • web.xml 需要配置自启动

    1
    2
    3
    4
    5
    6
    7

    <servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>HelloServlet</servlet-class>
    <!-- 自启动 数字越[小]优先级越[高], 取值范围1-99-->
    <load-on-startup>10</load-on-startup>
    </servlet>
  • 且将业务逻辑写在servlet 中的init()部分

    1
    2
    3
    4
    5
    6
    7
    /**
    * 在此书写逻辑
    */
    @Override
    public void init(){
    System.out.println("init of Hello Servlet");
    }``java

1.4 request常用方法

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
System.out.println("3. ========== service ============= 函数");

System.out.println("浏览器发出请求时的完整URL,包括协议 主机名 端口(如果有j):"
+ request.getRequestURL()); //request.getRequestURL();

System.out.println("浏览器发出请求时的资源名部分,去掉了协议和主机名: "
+ request.getRequestURI()); //request.getRequestURI();

System.out.println("请求行中的参数部分: "
+ request.getQueryString()); //request.getQueryString();

System.out.println("浏览器所处于的客户机的IP地址: "
+ request.getRemoteAddr()); //request.getRemoteAddr();

System.out.println("浏览器所处于的客户机的主机名: "
+ request.getRemoteHost()); //request.getRemoteHost();

System.out.println("浏览器所处的客户机使用的网络端口"
+ request.getRemotePort()); //request.getRemotePort();

System.out.println("服务器的ip地址"
+ request.getLocalAddr()); //request.getLocalAddr()

System.out.println("服务器的主机名"
+ request.getLocalName()); //request.getLocalName();

System.out.println("客户机的请求方式"
+ request.getMethod()); //request.getMethod()
  • 运行结果 例子
    20210405155741