Writer :BYSocket(泥沙砖瓦浆木匠)
微 博: BYSocket
豆 瓣: BYSocket
FaceBook: BYSocket
Twitter : BYSocket
“眨眼间,离上一篇写技术博文时隔1个月。怕自己真的生疏了,都是备案太慢惹得。哈哈,继续high~ ”
从 [JavaEE 要懂的小事] Http相关 ,一直想写点Web开发相关的。最近项目接口开发紧,还有准备新的九月份战斗。JDK IO源码就隔一段落,温故知新看看 Servlet & JSP 相关。把自己基础累积回顾一遍,并和大家分享分享一些心得和代码。这里应该涉及到一部分源码,开发思想和一些手工做出的图。喜欢java,或者有一定Java开发经验的多提宝贵意见。
从事web开发的人,会很清楚一个东西叫 HTTP服务器 ,比如JEE开发— Tomcat , Jetty ,.NET开发— ISS 等。HTTP服务器是使用 HTTP (超文本传输协议) 与客户机浏览器进行信息交流。下面就是 HTTP服务器 简单交互图:(来自 [JavaEE 要懂的小事] Http相关 博客)
HTTP服务器 是 Web服务器 的一种,也是开发最常见的,自然还有其他方式进行信息交互,比如 FTP文件服务器 …
Web服务器是可以向发出请求的浏览器提供文档的程序。其核心过程为
连接过程 — 请求 过程 — 应答 过程 — 关闭连接
如图,Tomcat 包含了 核心服务 模块: Connector 连接模块 和 Container 容器。Tomcat Server 核心是一个 Servlet/JSP Container 。对每一个 HTTP 请求,过程如下
— Servlet 来分析 请求 ( HttpServletRequest )
— 调用其 service 方法,进行业务处理
— 产生相应的 响应 ( HttpServletResponse )
如图:
蓝色线指向过程是 请求 ,绿色线指向过程是 响应 过程。也就是上面Web服务器核心过程:“ 连接过程 — 请求过程 — 应答过程 — 关闭连接 ”
什么是Servlet?(每次都会不停的问自己,这是什么“What”?紧接着应该是什么用“How”吧)
在 JavaEE 6文档 中,介绍如下
“ Servlet 是运行在 Web服务器 的Java小程序。Servlet可以获取并针对Web客户端的 请求作出响应 。一般情况下,通过 HTTP ,即超文本传输协议,进行传输通信。”
A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol.
在 JavaEE 6文档 中,是这样介绍 HttpServlet :
“HttpServlet 提供了一个能被继承后创建一个适应Web网站的 Http Servlet 的抽象类。”
Provides an abstract class to be subclassed to create an HTTP servlet suitable for a Web site.
光说不练假把式,练一个“Hello,Servlet/JSP World!”:
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; /* * Copyright [2015] [Jeff Lee] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Jeff Lee * @since 2015-6-25 19:46:45 * HelloWrold案例 */ @WebServlet(urlPatterns = "/helloWorld.html") public class HelloWorldServletT extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // 获取输出打印对象 PrintWriter out = resp.getWriter(); out.println("Hello,Servlet/JSP World!"); } }
右键该HelloWorldServletT.java文件 — Run As — Run On Server — 选择Tomcat服务器 — Finish即可
等待片刻,你可看到网页上如下输出。这就是客户端从HttpServlet获取到的响应:
休息一下吧~ 看看小广告:
开源代码都在我的gitHub上哦 — https://github.com/JeffLi1993
@WebServlet(urlPatterns = "/helloWorld.html")
@WebServlet(urlPatterns = { "/helloWorld01.html", "/helloWorld02.html" }
— doGet , 服务于 HTPP GET 请求
— doPost , 服务于 HTTP POST 请求
— doPut , 服务于 HTTP PUT 请求
— doDelete,服务于 HTTP DELETE 请求
…
如图:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_get_not_supported"); if (protocol.endsWith("1.1")) { resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg); } else { resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); } }
这里就简单的获取了下HTTP协议及Http Local信息,然后可以协议是否是1.1,做出分别是405或者400HTTP状态码的响应。
回到HelloWorldServletT.java 这里:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取输出打印对象 PrintWriter out = resp.getWriter(); out.println("Hello,Servlet/JSP World!"); }
完毕!哦还有一点补充补充 补充:
print,这里还好一句话。如果打印个table会很麻烦,因此有一个JSP的东西出现了,是Servlet的HTML化身。
又回到这个简单的 Get Servlet代码:
public class HelloWorldServletT extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ // 获取输出打印对象 PrintWriter out = resp.getWriter(); out.println("Hello,Servlet/JSP World!"); } }
这过程总结如下:
— 从浏览器(Client) 获取连接”/helloWorld.html”
— Container 模块会做以下事情
—— 分析HTPP请求信息,组装成 HttpServletRequest 对象
—— 创建新的 HttpServletResponse 对象
—— 根据路由配置,搜索相应的 Servlet ,并 创建一个线程 用于处理本次请求。此时线程会将上面 Request 和 Response 对象的 索引 , 传递给Servlet
— 新线程中的Servlet处理 逻辑
— 线程结束 后,通过 HttpServletResponse 对象的 PrintWriter ,返回浏览器一个信息
过程图如下:
有些面试题会这样问:
不是,一个servlet实现类 只会有一个实例对象 ,多个线程是可能会访问同一个servlet实例对象的, 线程安全问题 都是由 全局变量 及 静态变量 引起的。
因此,Servlet对象实例化是在以 第一次请求 此Servlet时,如果访问后,实例对象存在 内存 中,只会在服务器停止时,它才会消失。它不会随着各个线程结束而结束。因此下次访问Servlet时, Servlet Container 会搜索相应的 Servlet ,如果 不存在 , Container新建 相应的 Servlet 。这也是我们想要的结果。
发现这一博客写的太多,回头一看。可以写成三个文章了。言归正传本文要点如下
5、欢迎点击我的博客及GitHub — 博客提供RSS订阅哦
———- http://www.bysocket.com/ ————- https://github.com/JeffLi1993 ———-