Tomcat基础知识2

52 阅读4分钟

文章目录

1. Servlet

注意Servlet类是单例模式,即每个对应的Servlet子类只能有一个实例

1.1 Servlet在服务器充当的角色

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PB3u2xAL-1572859856183)(en-resource://database/6683:1)]

  Servlet运行流程图

1.2 客户端的请求方式分类

1.3 Servlet类的继承关系、以及方法介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ooiSwVg2-1572859856191)(en-resource://database/6685:1)]





  将处理HTTP请求的Servlet一般需继承该抽象类,因为其有对Http协议的处理


  封装HTTP请求报文

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XHTc3JNC-1572859856208)(en-resource://database/8027:1)]


  封装HTTP回应报文


1.4 ServletContext、ServletConfig、Servlet

  • 一个Web项目(也叫Web应用)对应一个ServletContext

    1. 启动项目时就自动创建ServletContext实例
    2. 当前项目下的所有Servlet共享这个ServletContext实例 - 意味着同项目下Servlet数据共享
    3. ServletContext-path:localhost:8080/项目名

  • 每个ServletConfig对应Servlet

    1. 存储Web.xml中的 子标签下的键值对、以及Servlet类名
    2. 存储Servlet的上下文
    3. 应用:可存储数据库的连接字符串、到时页面请求时可从ServletConfig中直接拿连接字符串即可

  • Servlet根据ServletConfig的信息进行实例化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gixGU8cF-1572859856210)(en-resource://database/6939:1)]

根据上图的信息即是下面代码输出的信息


代码演示

public class ConfigTest extends HttpServlet{
	
	ServletConfig config;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		this.config = config;
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println(config.getServletName());    // Servlet子类名
		List<String> list = Collections.list(config.getInitParameterNames()); // 初始参数名容器
		System.out.println(list);       // 打印所有初始的参数名
		for(String str : list) {
			System.out.println(str + ": " + config.getInitParameter(str));   // 返回当前Servlet的参数键值对
		}
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.service(req, resp);
	}
	
}


1.4 客户端、servlet容器、servlet对象 三者间请求回应关系

Servlet容器管理所有的servlet对象 - 故客户端是与服务器的Servlet容器进行交流

如果指定的load-on-startup没有设置,则只有HTTP请求的时候才创建、只要该属性设置了,服务器启动就会自动的实例化该servlet对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EV69ATDj-1572859856221)(en-resource://database/6941:1)]

sequenceDiagram
    客户端 ->> Servlet容器: 1. HTTP请求
    alt servlet寻找不到
        Servlet容器 ->> Servlet: 2. 创建实例 - init()
    end
    Servlet容器 ->> Servlet: 3. HTTP处理 - service()
    Servlet ->> Servlet容器: 4. 处理信息
    Servlet容器 ->> 客户端: 5. Http报文回复
    Servlet容器 ->> Servlet: 6. 销毁Servlet - destory()


1.5 同一Servlet对象多线程访问

2. 客户端请求方式


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9n1ut04a-1572859856232)(en-resource://database/6917:1)]

  HTML代码实例


<!--from中的action即将表单的数据送到目的url、method:数据的传输方式-->

<form action="./formProcess.html" method="get">
    姓名:<input type="text">
    <br/>
    密码:<input type="password">
    <br/>
    <input type="submit">"
</form>

  Servlet代码实例

@WebServlet(urlPatterns = "/formProcess.html")   // 设定该Servlet对象的访问域名
public class FormProcess extends HttpServlet {    // 继承HttpServlet就是Servlet子类
	@Override
	
    protected void getRestult(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		req.setCharacterEncoding("UTF-8");
		resp.setCharacterEncoding("UTF-8");
		resp.setContentType("text/html;charset=UTF-8");    // 
		PrintWriter pw = resp.getWriter();
        
		Enumeration<String> ParameterNames = req.getParameterNames();
		List<String> list = Collections.list(ParameterNames);
		pw.write(list.toString());
		pw.write("<br>");
		for (String name : list) {
			pw.write(name + ":" + req.getParameter(name) + "<br>");
		}
		pw.close();
    }
    
    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		getRestult(req, resp);
	}
    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		getRestult(req, resp);
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.service(req, resp);
	}

}


  1. 当提交上面的表单后即method=“get”,action的URL在地址栏的表现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cA6zTK6P-1572859856241)(en-resource://database/6919:1)]


  2. 当修改上面的表单请求方法并提交后即method=“post”,表单内的数据在HTTP请求体里面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BM8k1s8i-1572859856252)(en-resource://database/6921:1)]


3. PrintWriter.close()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fi6MJKae-1572859856263)(en-resource://database/6927:1)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qGNN1Pgn-1572859856273)(en-resource://database/7057:1)]

一旦关闭,HTTP响应报文不能在更改、已经为提交状态 - 故一般将此方法放在servicec后面

  代码测试



1. index2.html页面

<body>
     <a href="./close.do">printWriter.close()测试</a>
</body>

  2. clsoe.do页面

@WebServlet(
           description = "测试printWriter.close()方法", 
           urlPatterns = { "/close.do" }
           )
public class TestClose extends HttpServlet {

     protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           super.service(request,response);
     }

     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           PrintWriter pw = response.getWriter();
           response.setContentType("text/plain");    // 页面显示内容编码第一次更改
           pw.write("<h1>I love Tomcat</h1>");
           pw.close();                                  // printWriter提前关闭
           response.setContentType("text/html");   // 页面显示内容编码第二次更改
     }
}

  页面显示结果

1. 点击index2.html页面的超链接 - F12查看Network请求、响应资源信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TN8rREzS-1572859856284)(en-resource://database/6923:1)]

2. TestClose中的pw.close()放置doGet()末尾,再重复上述1步骤

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uFt4bE5r-1572859856292)(en-resource://database/6925:1)]


4. 重定向、请求分派的区别

Servlet容器的root路径:http://localhost:8080/  等价于   /

Servlet的上下文路径:http://localhost:8080/项目名 → req.getContextPath()

./ = 直接写子域名:点表示当前地址栏最后一个斜杠前的所有字符串

4.1 重定向

不管你是相对还是绝对URL,系统都会自动帮你转为绝对URL


重定向时序图:客户端请求多次

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-siW8TaaC-1572859856300)(en-resource://database/6931:1)]

/:斜杆即是 http://llocalhost:8080

  代码实例:resp.sendRedirect( String )

@WebServlet(
		name = "RedirectServlet", 
		urlPatterns = { "/redirect/one.do" }
		)
public class Redirect extends HttpServlet {

	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.service(req,resp);
	}

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.sendRedirect("/JavaWeb_learning/index2.html");		
        // 重定向可写成地址: ../index2.html  或者   req.getContextPath + "/index2.html"
	}
}

  运行上述代码步骤

  1. 地址栏输入:http://localhost:8080/JavaWeb_learning/redirect/one.do
  2. 然后自动会跳转到 index2.html 页面
  3. 可看到下图客户端发了两次HTTP请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ssbt3Jnj-1572859856313)(en-resource://database/6933:1)]

4.2 请求分派

path:只能写相对URL

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MinSii0C-1572859856321)(en-resource://database/7753:1)]

/ : 斜杆即是 http://llocalhost:8080/项目名

  代码实例:req.getRequestDispatcher( String ).forward( req, resp )

  index2.html页面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
     <h1>分派后的页面</h1>
</body>
</html>

  Servlet子类

@WebServlet(urlPatterns = {"/dispatch.do"})
public class Dispatch extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		RequestDispatcher d = req.getRequestDispatcher("./index2.html");
		d.forward(req, resp);
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.service(req, resp);
	}
	
}

  运行上述代码步骤

  1. 地址栏输入:http://localhost:8080/JavaWeb_learning/dispatch.do
  2. 然后自动会跳转到 index2.html 页面、并且地址栏依然是1的请求URL
  3. 可看到下图客户只发出一次HTTP请求、并且返回的内容不是dispatch.do的内容而是 index2.html的内容
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YxQiRypJ-1572859856332)(en-resource://database/6935:1)]