深入拆解Tomcat & Jetty
李号双
eBay技术主管
立即订阅
6067 人已学习
课程目录
已完结 44 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | Java程序员如何快速成长?
免费
模块一 必备基础 (4讲)
01 | Web容器学习路径
02 | HTTP协议必知必会
03 | 你应该知道的Servlet规范和Servlet容器
04 | 实战:纯手工打造和运行一个Servlet
模块二 整体架构 (9讲)
05 | Tomcat系统架构(上): 连接器是如何设计的?
06 | Tomcat系统架构(下):聊聊多层容器的设计
07 | Tomcat如何实现一键式启停?
08 | Tomcat的“高层们”都负责做什么?
09 | 比较:Jetty架构特点之Connector组件
10 | 比较:Jetty架构特点之Handler组件
11 | 总结:从Tomcat和Jetty中提炼组件化设计规范
12 | 实战:优化并提高Tomcat启动速度
13 | 热点问题答疑(1):如何学习源码?
模块三 连接器 (9讲)
14 | NioEndpoint组件:Tomcat如何实现非阻塞I/O?
15 | Nio2Endpoint组件:Tomcat如何实现异步I/O?
16 | AprEndpoint组件:Tomcat APR提高I/O性能的秘密
17 | Executor组件:Tomcat如何扩展Java线程池?
18 | 新特性:Tomcat如何支持WebSocket?
19 | 比较:Jetty的线程策略EatWhatYouKill
20 | 总结:Tomcat和Jetty中的对象池技术
21 | 总结:Tomcat和Jetty的高性能、高并发之道
22 | 热点问题答疑(2):内核如何阻塞与唤醒进程?
模块四 容器 (8讲)
23 | Host容器:Tomcat如何实现热部署和热加载?
24 | Context容器(上):Tomcat如何打破双亲委托机制?
25 | Context容器(中):Tomcat如何隔离Web应用?
26 | Context容器(下):Tomcat如何实现Servlet规范?
27 | 新特性:Tomcat如何支持异步Servlet?
28 | 新特性:Spring Boot如何使用内嵌式的Tomcat和Jetty?
29 | 比较:Jetty如何实现具有上下文信息的责任链?
30 | 热点问题答疑(3):Spring框架中的设计模式
模块五 通用组件 (4讲)
31 | Logger组件:Tomcat的日志框架及实战
32 | Manager组件:Tomcat的Session管理机制解析
33 | Cluster组件:Tomcat的集群通信原理
特别放送 | 如何持续保持对学习的兴趣?
模块六 性能优化 (8讲)
34 | JVM GC原理及调优的基本思路
35 | 如何监控Tomcat的性能?
36 | Tomcat I/O和线程池的并发调优
37 | Tomcat内存溢出的原因分析及调优
38 | Tomcat拒绝连接原因分析及网络优化
39 | Tomcat进程占用CPU过高怎么办?
40 | 谈谈Jetty性能调优的思路
41 | 热点问题答疑(4): Tomcat和Jetty有哪些不同?
结束语 (1讲)
结束语 | 静下心来,品味经典
深入拆解Tomcat & Jetty
登录|注册

04 | 实战:纯手工打造和运行一个Servlet

李号双 2019-05-18
作为 Java 程序员,我们可能已经习惯了使用 IDE 和 Web 框架进行开发,IDE 帮我们做了编译、打包的工作,而 Spring 框架在背后帮我们实现了 Servlet 接口,并把 Servlet 注册到了 Web 容器,这样我们可能很少有机会接触到一些底层本质的东西,比如怎么开发一个 Servlet?如何编译 Servlet?如何在 Web 容器中跑起来?
今天我们就抛弃 IDE、拒绝框架,自己纯手工编写一个 Servlet,并在 Tomcat 中运行起来。一方面进一步加深对 Servlet 的理解;另一方面,还可以熟悉一下 Tomcat 的基本功能使用。
主要的步骤有:
1. 下载并安装 Tomcat。
2. 编写一个继承 HttpServlet 的 Java 类。
3. 将 Java 类文件编译成 Class 文件。
4. 建立 Web 应用的目录结构,并配置web.xml
5. 部署 Web 应用。
6. 启动 Tomcat。
7. 浏览器访问验证结果。
8. 查看 Tomcat 日志。
下面你可以跟我一起一步步操作来完成整个过程。Servlet 3.0 规范支持用注解的方式来部署 Servlet,不需要在web.xml里配置,最后我会演示怎么用注解的方式来部署 Servlet。
1. 下载并安装 Tomcat
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Tomcat & Jetty 》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(43)

  • feitian
    既然是纯手工,就应该把servlet那套完整的写出来,不应该再用tomcat容器而应该手写实现tomcat的核心代码。最核心的应该是类似HttpServlet功能的实现,把这个从最初的servlet接口实现了才算讲透,不然还是有点和稀泥的感觉。我觉得应该按照这种思路讲会更好,请参考我写的mytomcat,https://github.com/feifa168/mytomcat
    2019-05-20
    9
    106
  • Monday
    1、postman
    2、curl 命令发送post
    3、用HttpClient发送

    周六早上坚持打卡,本章节绝大多数知识以前有接触过,只有@WebServlet注解是新知识,现在业务开发一般都是写SpringMVC容器中的Controller来代替类似文中的Servlet类。

    问题:基于Spring+SpringMVC+Mybais的框架搭建的项目,平常开发的都是写Controller与Service、DAO。
    1、请问Servlet容器只管理DispatchServlet这一个Servlet吗?
    2、有什么可视化工具可以直接查看各种容器中管理的对象吗?

    谢谢!

    作者回复: 1. 你可以向Servlet容器注册多个Servlet。
    2. 你看这个有没有帮助
    https://github.com/spring-projects/spring-framework/issues/14296

    2019-05-18
    8
  • darren
    发现xml与注解不能同时起作用,那在用xml方式的老项目中就没办法使用注解的方式了吗?

    作者回复: web.xml 和注解可以同时工作的。

    例子里的web.xml和注解不能同时工作的原因是web.xml中的配置metadata-complete="true", 你需要把它设置成metadata-complete="false"。

    metadata-complete为true的意思是,告诉Tomcat不要去扫描Servlet注解了。

    2019-05-18
    7
  • allean
    IDE和框架诞生之初是为了让程序员从繁琐的底层配置中抽离出来专注于业务开发,然而大多数人在享受IDE和框架带来的便捷时,也成了温水里的青蛙,对于实现原理认识模糊,渐渐沦落为一个CRUD,这不是一件好事,啊~幡然醒悟
    2019-05-18
    6
  • youknowmjj
    @Amanda 不知道怎么直接回复你,我跟你一样也是遇到乱码的问题。我也设置了response.setCharacterEncoding(utf8),在getWriter之前,但依然是一样的乱码。
    原因在与javac编译生成的class文件是用的gbk的编码。换句话说,你生成的class源文件就已经是中文乱码了。
    所以在javac的时候加上 -encoding UTF-8就好了。
    ps:我是Windows的环境。
    2019-05-19
    5
  • Amanda
    老师,实践中发现个问题:虽然response.setContentType("text/html;charset=utf-8"),但是out.println中有输出中文还是乱码的

    作者回复: 调下顺序,像下面这样:
    response.setContentType("text/html; charset=utf-8");
    PrintWriter out = response.getWriter();

    getWrite的源码如下:
    ------
        public PrintWriter getWriter()
            throws IOException {

            if (usingOutputStream) {
                throw new IllegalStateException
                    (sm.getString("coyoteResponse.getWriter.ise"));
            }

            if (ENFORCE_ENCODING_IN_GET_WRITER) {
                /*
                 * If the response's character encoding has not been specified as
                 * described in <code>getCharacterEncoding</code> (i.e., the method
                 * just returns the default value <code>ISO-8859-1</code>),
                 * <code>getWriter</code> updates it to <code>ISO-8859-1</code>
                 * (with the effect that a subsequent call to getContentType() will
                 * include a charset=ISO-8859-1 component which will also be
                 * reflected in the Content-Type response header, thereby satisfying
                 * the Servlet spec requirement that containers must communicate the
                 * character encoding used for the servlet response's writer to the
                 * client).
                 */
                setCharacterEncoding(getCharacterEncoding());
            }

            usingWriter = true;
            outputBuffer.checkConverter();
            if (writer == null) {
                writer = new CoyoteWriter(outputBuffer);
            }
            return writer;
        }
    -----

    你看注释里它说:如果调这个方法之前没有指定Response的字符编码,就用默认的ISO-8859-1,ISO-8859-1不包括中文字符。

    2019-05-18
    5
  • 今夜秋风和
    老师,验证的时候默认增加了 super.doGet(req, resp);在http1.1写一下不能工作,查看httpServlet 源码里面 对协议做了限制,http 1.1 协议默认不支持。这个为什么是这样设计的呢?
    源代码:
            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);
            }
    第二个是如果是那个注解访问的,可以不用删除web.xml,把web.xml里面的url-pattern 改成注解同样的路由,也可以支持;如果web.xml 路由自定义一个的话,测试发现自定义的会有404,是不是注解的路由优先级会更高呢?
    3.如果把web.xml删除,servlet容器启动的时候是不是会自动扫描注解类,将它注册到容器中?

    作者回复: super.doGet(req, resp); 调的是HttpServlet的doGet方法,但是这个doGet需要你去实现的。

    HttpServlet的service方法会调doXXX方法,并且HttpServlet里的各种doXXX方法的默认实现都是直接返回错误。

    为什么HttpServlet要这样设计呢?这是因为它需要做一个限制:程序员要么重写HttpServlet的service方法,要么重写HttpServlet的doXXX方法。

    web.xml和注解可以同时工作,你需要把web.xml中的metadata-complete="true"设置成false。

    Tomcat启动时会扫描注解,同时记下Servlet的名字和映射路径,如果你设置了延迟记载Servlet,通过浏览器访问时Tomcat才会加载和实例化Servlet。

    2019-05-18
    5
  • 风翱
    可以利用工具,例如postman。 也可以编写代码,利用http的post方法去调用。 或者像楼上所说的不管通过get还是post都通知转发到doPost中。
    2019-05-18
    4
  • 吃饭饭
    分享一个编译源码的帖子:https://mp.weixin.qq.com/s/wp1LZcdK2eLRZU3HlubW9w
    2019-09-26
    2
  • Geek_0db340
    表单提交method=post 就可以啦
    2019-05-18
    2
  • KL3
    把业务逻辑写在dopost里,然后doget方法调用dopost方法
    2019-05-18
    2
  • 业余爱好者
    “javac -cp ./servlet-api.jar MyServlet.java”执行报错:
    "MyServlet.java:16: 错误: 编码GBK的不可映射字符
            System.out.println("MyServlet 鍦ㄥ鐞? get锛堬級璇锋眰...");"
    换成:“javac -encoding UTF-8 -cp ./servlet-api.jar MyServlet.java”解决。百度搬运工。。
    2019-06-18
    1
  • 桔子
    李老师,doGet方法的request和response的初始化代码在哪里呢,只知道是servlet容器创建的,但是去哪里可以看到容器初始化response的源码呢。

    作者回复: 在Tomcat中CoyoteAdapter类的service方法里

    2019-05-31
    1
  • Geek_ebda96
    李老师,请教一个问题,你这里所说的servlet和spring mvc里面的controller是什么关系,servlet里面可以直接接收请求,处理请求业务,controller只是通过dispatch servlet再接入进来的?

    作者回复: 你说的没错,具体是这样的 Tomcat的Wrapper组件-Filter-DispatcherServlet-Controller

    2019-05-23
    1
  • kmmshmily
    这个demo 大学期间一直这样写啊 最后才用Spring的
    2019-05-23
    1
  • 清风
    注解是高版本的Servlet才支持的吧,好像是2.5以上

    作者回复: Servlet3.0开始支持

    2019-05-22
    1
  • Howard
    代码放在github上需要注意开源协议,像apache这种协议明确说明受美国出口管制的
    2019-05-22
    1
    1
  • 张济增
    看着前几章跟 head first servlet jsp差不多,先来个基础
    2019-05-20
    1
  • Geek_bde3dc
    最简单的办法就是在doGet里调用doPost😁
    2019-05-18
    1
  • GeekAmI
    curl -X POST http://127.0.0.1:8080/MyWebApp/myAnnotationServlet
    2019-11-26
收起评论
43
返回
顶部