Tomcat基础知识2

23 篇文章 0 订阅

1. Servlet

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

1.1 Servlet在服务器充当的角色

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

  Servlet运行流程图

服务端接受Http请求
HttpServleRequest类取得请求信息 - 请求头、请求参数数据
调用其他类方法 → 完成更具体的业务功能
实现Web组件的跳转 → 包括重定向、请求转发
生成Http响应报文给客户端(浏览器)

1.2 客户端的请求方式分类
客户端请求方式
get
放到地址栏明码输出、用于查询数据
head
post
数据放到http请求体中、不会把数据缓存在内存中、用于登录
put
delete
options
trace

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

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


Servlet接口
'init(配置对象)' → 实例化一个Servlet对象
仅调用一次,即对应的具体类只有一个实例
调用该运行时抛出异常、重新载入该类再次执行该方法
service( ServletRequest, ServletResponse )
作用:回应请求,返回给客户端请求处理结果
实例化Servlet对象才能调用该方法
通常用于多线程,切记记得同步等问题
destory()
销毁servlet对象
执行时机:service()执行完毕,或者 处理请求超时
getServletConfig()
返回一个有关包含Servlet启动信息的对象
getServletInfo()
返回关于作者、版本、版权的字符串


ServletConfig接口
getInitParameter(String)
返回实参传入Servlet初始化参数的名字的值
getInitParameterNames()
返回一个存储字符串的枚举容器对象、枚举内元素:Servlet初始化参数的名称
getServletContext()
返回ServletContext对象 - 作用:用来与Servlet容器进行互动交流
getServletName()
返回Servlet对象的名称:未注册、命名的返回该对象类名称,已注册则返回服务器管理的Web应用部署描述


GenericServlet抽象类
实现Servlet接口的实现方法
service(ServletRequest req, ServletResponse res) -- 抽象方法,子类需重写
ServletConfig接口的实现方法
init()
log(String msg)
将msg信息写到Servlet记录文件中
log(String, Throwable)
将msg信息、对于抛出异常的一系列堆栈路径写到Servlet记录文件中


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

HttpServlet抽象类
继承GenericServlet抽象类的方法
service(ServletRequest req, ServletResponse res) -- 重写该方法、做出对客户端的响应、根据客户端的请求方式而做出不同的响应
各种doxx() --- 客户端的请求方式
doGet() → 处理客户端Get请求
doPost() → 处理客户端Post请求
剩下就不写、总之共7种请求方式
service(ServletRequest req, ServletResponse res) 重载、用于请求分派、一般不需要重写该方法


  封装HTTP请求报文

HttpServletRequest接口
getRequestDispatcher(String):得到分派对象
继承ServletRequest接口的方法
各种返回的信息getxxx方法
各种返回的信息getxxx方法
客户端
主机名、Ip地址、端口号、用户登录名
服务端
Ip地址、服务器所在语言地区、服务器名字、端口号
Servlet的信息
servelContext对象、项目名称、请求的部分路径、协议、请求方式
参数信息
即跟随页面链接、或者包体里面的实参数据

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


  封装HTTP回应报文

HttpServletResponse接口
继承ServletResponse接口的方法
各种关于Http回复报文的信息 getxxx()方法
设置Http回复报文的信息 setxxx()方法
sendReadirect(String):重定向


1.4 ServletContext、ServletConfig、Servlet
1对多
1对1
1对多
1对1
Servlet容器
ServletContext
Web项目
Servlet对象
ServletConfig对象

  • 一个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对象多线程访问
解决方案
1. 共享的数据代码块使用 synchronized关键字 进行同步
2. Servlet具体类 尽量少使用 成员变量(必须同步)
3. 同步代码块的范围尽量缩小

2. 客户端请求方式

常用请求
get:地址栏长度有限制、明文传输
标签的连接
标签的属性 method=get
post:数据大小不限制、放置在包体中
标签的属性 method='post'


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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()

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

资源获取
重定向 - redirect
HTTP请求多次
可访问不同站点资源
地址栏为重定向URL
请求分派 - dispatch
HTTP请求仅1次
仅当前站点资源
地址栏为首次输入的URL

4.1 重定向

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


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

浏览器(客户端) 服务器(Ser Servlet对象 1. HTTP请求 2. 查找Servlet1 3 .重定向Servlet2 4. Http响应报文:重定向Servlet2 5. HTTP请求 6. 查找Servlet2 7. 查找成功并返回数据 8. Http响应报文 浏览器(客户端) 服务器(Ser Servlet对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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/项目名

客户端(浏览器) 服务器(Ser Servlet1对象1 Servlet对象2 HTTP请求 查找Servlet1 分派 分派成功,并返回数据 HTTP响应报文 客户端(浏览器) 服务器(Ser Servlet1对象1 Servlet对象2

  代码实例: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)]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值