执行过程

Tomcat Server处理一个http请求的过程

假设来自客户的请求为:http://localhost:8080/wsota/wsota_index.jsp

  1. 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
  2. Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
  3. Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host
  4. Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
  5. localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context
  6. Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
  7. path="/wsota"的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet
  8. Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
  9. 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
    10)Context把执行完了之后的HttpServletResponse对象返回给Host
    11)Host把HttpServletResponse对象返回给Engine
    12)Engine把HttpServletResponse对象返回给Connector
    13)Connector把HttpServletResponse对象返回给客户browser

servlet接口关系图

HttpServlet抽象类中实现了service

    @Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException{HttpServletRequest  request;HttpServletResponse response;if (!(req instanceof HttpServletRequest &&res instanceof HttpServletResponse)) {throw new ServletException("non-HTTP request or response");}request = (HttpServletRequest) req;response = (HttpServletResponse) res;service(request, response);}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 logicdoGet(req, resp);} else {long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);if (ifModifiedSince < lastModified) {// 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 lessmaybeSetLastModified(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);}}

所以需要重写doGet和doPost

@WebServlet(name = "ServletDemo2", value = "/ServletDemo2")
public class ServletDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("hello servlet");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request,response);}
}

Servlet 生命周期

init : 请求第一次到达servlet 时,对象创建并初始化成功。
service : servlet 一直存在,并提供服务
destroy:服务器宕机,停机销毁servlet对象时触发

@WebServlet(name = "ServletDemo03", value = "/ServletDemo03")
public class ServletDemo03 extends HttpServlet {@Overridepublic void init() throws ServletException {System.out.println("servlet 对象创建了,初始化成");}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("接收到客户端请求");}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}@Overridepublic void destroy() {System.out.println("对象销毁了。。。");}
}

servlet线程安全问题

Servlet 是单实例
一个浏览器代表一个线程,多个浏览器代表多个线程。
定义类成员要谨慎。如果是共用的,并且只会在初始化时赋值,其他时间都是获取,那么是没有问题的。
如果不是共用的,或者每次使用都有可能对其赋值,就要考虑线程安全问题,可将其定义到doGet或doPost方法内或者使用同步功能即可

@WebServlet(name = "ServletDemo4", value = "/ServletDemo4")
public class ServletDemo4 extends HttpServlet {private String username;@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {username = request.getParameter("username");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}PrintWriter writer = response.getWriter();writer.println("username = " + username );writer.close();}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}

定义到局部

    //private String username;@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}PrintWriter writer = response.getWriter();writer.println("username = " + username );writer.close();}

加同步锁

    private String username;@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {synchronized (this){username = request.getParameter("username");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}PrintWriter writer = response.getWriter();writer.println("username = " + username );writer.close();}}

映射方式

//@WebServlet(name = "ServletDemo5", value = "/ServletDemo5")
//@WebServlet(name = "ServletDemo5", value = "/ServletDemo5/zs/*")
@WebServlet(name = "ServletDemo5", value = "*.do")
public class ServletDemo5 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {PrintWriter writer = response.getWriter();writer.println("hello servlet");writer.close();}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}

简单demo

request.getRequestURI() : /ServletDemo6/vip
path.substring(path.lastIndexOf("/")) : /vip
原价:1000 优惠价:900.0

@WebServlet(name = "ServletDemo6", value = "/ServletDemo6/*")
public class ServletDemo6 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//定义商品金额int money = 1000;//获取访问资源路径String path = request.getRequestURI();System.out.println("request.getRequestURI() : " + path);path = path.substring(path.lastIndexOf("/"));System.out.println("path.substring(path.lastIndexOf(\"/\")) : " + path);//判断访问路径if ("/vip".equals(path)){System.out.println("原价:" + money + "\t" + "优惠价:" + (money*0.9));}else if("/vvip".equals(path)){System.out.println("原价:" + money + "\t" + "优惠价:" + (money*0.5));}else {System.out.println("原价:" + money + "\t");}}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}

Servlet 创建时机

ServletConfig

ServletConfig 是Servlet的配置参数对象,在Servlet的规范中,允许每个Servlet都提供一些初始化的配置。所以,每个Servlet都有一个自己的ServletConfig
作用:在Servlet的初始化时,把一些配置信息传递给Servlet
生命周期: 和Servlet相同

常用方法

public class ServletDemo7 extends HttpServlet {private ServletConfig config;@Overridepublic void init(ServletConfig config) throws ServletException {this.config = config;}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//根据key获取valueString encodingValue = config.getInitParameter("encoding");System.out.println(encodingValue);//获取Servlet的所有keyEnumeration<String> keys = config.getInitParameterNames();while (keys.hasMoreElements()){String key = keys.nextElement();String value = config.getInitParameter(key);System.out.println(key + "," + value);}//获取Servlet名称String servletName = config.getServletName();System.out.println(servletName);//获取ServletContext对象ServletContext servletContext = config.getServletContext();System.out.println(servletContext);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}
    <servlet><servlet-name>ServletDemo7</servlet-name><servlet-class>com.example.demo1.servlet.ServletDemo7</servlet-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>ZS</param-name><param-value>hello servletConfig</param-value></init-param></servlet><servlet-mapping><servlet-name>ServletDemo7</servlet-name><url-pattern>/ServletDemo7</url-pattern></servlet-mapping>

ServletContext

ServletContext 是应用上下文对象(应用域对象)。每个应用中只有一个ServetContext对象。
作用: 可以配置和获得应用的全局初始化参数,可以实现Servlet之间的数据共享
生命周期: 应用一加载则创建,应用被停止则销毁

域对象
域对象指的是对象有作用域。也就是有作用范围。域对象可以实现数据的共享。不同作用域的对象,共享数据的能力也不一样。
Servlet中,有4个域对象。ServletContext是其中之一,也是最大的作用域,也称application域,可以实现整个应用之间的数据共享


    <!--配置ServletContext--><context-param><param-name>globalEncoding</param-name><param-value>UTF-8</param-value></context-param><context-param><param-name>globalDesc</param-name><param-value>This is ServletContext</param-value></context-param>
@WebServlet(name = "ServletDemo8", value = "/ServletDemo8")
public class ServletDemo8 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取ServletContext对象ServletContext context = getServletContext();//根据key获取valueString value = context.getInitParameter("globalDesc");System.out.println("globalDesc = " + value);//获取应用的虚拟目录String contextPath = context.getContextPath();System.out.println("虚拟目录:" + contextPath);//根据虚拟目录获取绝对路径String realPath = context.getRealPath("/");System.out.println("虚拟目录的绝对路径" + realPath);}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request,response);}
}

globalDesc = This is ServletContext
虚拟目录:
虚拟目录的绝对路径/Users/Shared/study/javaWeb/MyWeb/demo1/src/main/webapp/

获取虚拟目录的绝对路径可以方便找到文件的绝对路径

ServletContext 用于数据共享

  private ServletConfig config;@Overridepublic void init(ServletConfig config) throws ServletException {this.config = config;}//获取ServletContext对象ServletContext servletContext = config.getServletContext();//获取ServletContext对象ServletContext context = getServletContext();context.setAttribute("username","zs");context.setAttribute("username","lisi");context.removeAttribute("username");

简单案例

webapp>addStudent.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>保存学生信息</title>
</head>
<body><form action="/studentServlet" method="get" autocomplete="off">学生姓名:<input type="text" name="username"><br/>学生年龄:<input type="text" name="age"><br/>学生成绩:<input type="text" name="score"><br/><button type="submit">保存</button></form>
</body>
</html>

web.xml

    <!--配置默认主页--><welcome-file-list><welcome-file>/addStudent.html</welcome-file></welcome-file-list><servlet><servlet-name>studentServlet</servlet-name><servlet-class>com.example.demo1.servlet.studentServlet</servlet-class></servlet><servlet-mapping><servlet-name>studentServlet</servlet-name><url-pattern>/studentServlet</url-pattern></servlet-mapping>

studentServlet

public class studentServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String age = req.getParameter("age");String score = req.getParameter("score");BufferedWriter bw = new BufferedWriter(new FileWriter(getServletContext().getRealPath("/stu.txt"), true));bw.write(username + "," + age + "," + score);bw.newLine();bw.close();PrintWriter pw = resp.getWriter();pw.println("Save Success~");pw.close();}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp);}
}

servlet ---- servlet入门相关推荐

  1. Servlet快速入门及运行流程

    一.Servlet快速入门 1.创建一个web工程 2.在JavaResource中src下创建一个包名称为com.myxq.servlet 3.在创建的servlet包当中创建一个class文件起名 ...

  2. Servlet的入门

    什么是Servlet? Servlet是运行在服务端的java小程序,是sun公司提供的一套规范,用来处理客户端请求.响应给浏览器的动态资源.Servlet是JavaWeb三大组件之一(Setvlet ...

  3. Day14-HTTP协议 web开发概述 servlet快速入门

    HTTP:HyperText Transfer Protocol 超文本传输协议 用于定义web浏览器和web服务器之间交换数据的过程 特点: 基于请求/响应模型的协议.请求和相应必须成对出现,现有请 ...

  4. Servlet知识入门

    Servlet: server applet Servlet概念:运行在服务器端的小程序,是Java EE的灵魂组成部分,servlet和jsp的依赖都在tomcat服务器中. Servlet就是一个 ...

  5. tomcat和servlet快速入门教程!!!

    Tomact和servlet快速入门教程 tomcat的入门必备知识 1.下载: 2.安装: 解压压缩包即可 3.卸载: 删除目录即可 4.启动: 5.关闭: 6.部署: 静态项目和动态项目 将tom ...

  6. servlet的入门使用

    servlet的入门使用 Servlet是什么 如何写一个Servlet 1. 使用eclipse创建maven的war项目,添加maven的jar依赖 2. 写一个java类,实现Servlet接口 ...

  7. JSP/SERVLET入门教程--Servlet 使用入门

    现在的JSP书籍有的是直接讲述JSP的使用,然后再讲解SERVERLET的使用;也有书籍是先讲述SERVERLET的使用,然后讲解JSP使用.个人认为第二种相对好一些,至于原因大家可以在学习体会到!所 ...

  8. Servlet快速入门

    目录 1.Servlet简介 2.代码实现 2.1.环境准备 2.2.实现servlet接口 2.3.配置web.xml文件 2.4.url-pattern的三种配置方式 2.5.快速创建Servle ...

  9. Tomcat服务器启动错误之Offending class: javax/servlet/Servlet.class

    引子 最近在基于Wex5项目开发中,遇到使用过程中与Tomcat功能有关的错误提示, 如题所示.最终的解决方法就是删除掉项目上与tomcat冲突的jar包. org.apache.catalina.l ...

  10. 异常处理记录: Servlet class X is not a javax.servlet.Servlet

    异常处理记录: Servlet class X is not a javax.servlet.Servlet 参考文章: (1)异常处理记录: Servlet class X is not a jav ...

最新文章

  1. 爬取--- https://www.exploit-db.com/ 下载POC较完善的代码【2】
  2. 欧拉工程第57题:Square root convergents
  3. 【caffe】windows下vs2013+opencv3.2.0+opencv_contrib(包含dnn)+cmake3.8编译与配置
  4. tcpsyn发生在哪层_必看面试题之计算机网络:来自一位拿到了腾讯和字节双offer的大佬...
  5. C++ Primer中文版(第4版 特别版)
  6. Mr.J-- jQuery学习笔记(十二)--移入移出事件电影排行榜小demo
  7. ie浏览器怎么取消代理浏览器_微软和IE渐行渐远,IE浏览器终将成为回忆
  8. 718. 最长重复子数组(JavaScript)
  9. 现在很多人到农村买桑叶来吃,桑叶真的可以吃吗?
  10. Linux下Socket网络编程send和recv使用注意事项
  11. unity3d实现序列帧动画
  12. 在 ASP.NET MVC 中充分利用 WebGrid (microsoft 官方示例)
  13. 微观经济学(第一课)笔记
  14. 批量打印软件导入Excel时如何保留两位小数
  15. html5字体加粗斜体,font设置字体加粗
  16. Intel Atom移动处理器惨败,还被用户和经销商起诉
  17. LeetCode(数据库)- 计算税后工资
  18. 在C ++中加载TORCHSCRIPT模型
  19. Word的样式库在 选项卡中_word排版应用:如何创建文本样式和表格样式
  20. 高考色彩静物组合想要画好?画之前注意下这8点:

热门文章

  1. 《2020信息消费战“疫”案例集》发布 邬贺铨院士作序推荐(附下载连接)
  2. java statement 存储过程_Java+sql server+CallableStatement调用存储过程三种情况 (转)...
  3. 日常踩坑:python新项目创建新的虚拟环境、pycharm无法安装install package工具、pip的缓存作用
  4. Leetcode中学到的SQL函数汇总
  5. 时序动作定位:Rethinking the Faster R-CNN Architecture for Temporal Action Localization(TAL-Net)
  6. 花书+吴恩达深度学习(二五)直面配分函数(CD, SML, SM, RM, NCE)
  7. Python的numpy基本用法
  8. 架构之技术复杂度与业务复杂度
  9. php中glob怎么用,如何在php中利用glob函数对文件进行遍历
  10. 吴恩达ex3_吴恩达Machine Learning Ex3 python实现