菜单开关

周梦康 发表于 2022-05-09 30 次浏览 标签 : 原创《Java Web 最佳学习路径》

注意这是系列,不是碎片知识。我会以每周1~2篇的速度进行更新。只要有1~2年的后端开发经验,保证无痛快速吸收 Java Web 实战开发经验。点赞转发,更新动力更强哟。

有人留言对 CGI 那节表示没意义,其实我认为把 CGI Serlvet 类比关系理解是打通 Java Web 学习任督二脉的关键。

我们先回顾下上节的重点知识,CGI 程序按照 CGI/1.1 协议规范在进程间通过环境变量来传递特定变量也就是环境变量,比如我们上节例子中,我们通过从QUERY_STRING获取参数 id 的值。

因为不再跨进程,所以 Web Server 里接收到的数据在 Web Server 里解析完毕之后,Servlet 程序可以直接使用,不再需要用环境变量中转。

相对比 CGI, Java Web 遵循的是 Servlet 规范,目前使用最广泛的是 Servlet/3.1,与 Web 服务器和 CGI 程序的交互方式不同,Servlet 要求 Web Server 和 Servlet 程序通过接口的方式对接。

Servlet 接口

最底层的接口也叫 Servelt 接口,通过调用service方法来将ServletRequest数据加工处理,保存数据到ServletResponse中。

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

为了方便大家开发,在 javax(java是核心包,javax的x是extension的意思,也就是扩展包)中,又提供了一个通用 Servlet (GenericServlet)来实现它,而针对 Web HTTP 请求,有提供了HttpServlet继承GenericServlet,这样大家做 Web 开发,编写自己的 Servlet 程序时,只需要继承HttpServlet即可。如下图的DemoServlet

编写第一个 Servlet

说了这么多理论知识,开始动手做个小实验吧,写 Java 如果用 vim 可能比较困难,最好还是用比较现代的工具,现在大家多数都是用的 IntelliJ Idea,因为是第一个 Java 程序,所以还是手摸手截图下,防止劝退

生成完毕之后,就如下图,maven 比较流行的包管理方式,就像 php 的 composer 一样。

Java Web 最佳学习路径 - Servlet 初体验

因为要实现 servlet 接口不在 jdk 里,所以这里要引入 javax 扩展包里的 servlet 包,否则无法继承

根据 java 包中心仓库里搜索到的结果 https://search.maven.org/artifact/javax.servlet/javax.servlet-api/3.1.0/jar 添加到 pom.xml

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>

编写第一个 Servlet 类,复写父类的doGet方法,实现一个 Get 请求的 Servlet,通过HttpServletResponse输出一段hello world

package net.mengkang;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class DemoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        resp.setContentType("text/html;charset=utf-8");
        out.println("hello world");
    }
}

编译之后生成的文件如截图

程序的编写已经符合 Servlet 规范了,Servlet 规范约束的不仅仅是后端 Servlet 程序,也同样约束 Web Server ,这样才能按照协议融合对接。所以需要选择一个 Servlet Web Server。这里选择 Tomcat

比如 netty 虽然也能做 Web Server 但是就不符合 Servlet 规范,以 netty 为网络通讯基础的 jetty 则符合 Servlet 规范。

下载 Tomcat 8

https://tomcat.apache.org/download-80.cgi

不要选择 tmocat 10,servelt 包名有变化

访问 http://localhost:8080/ 就能看到 tomcat 默认页面了,按照 tomcat 的规范配置下我的 webapp

配置 webapp

按照 tomcat 的程序设计,需要在其webapps新建一个目录(demo)作为测试 app 的根目录,然后配置web.xmlservlet代码,结构如下

$ tree webapps/demo
webapps/demo
└── WEB-INF
    ├── classes
    │   └── net
    │       └── mengkang
    │           └── DemoServlet.class
    └── web.xml

web.xml 是 web app 的配置文件总入口,比如这里的 servlet 的定义,和 servlet映射的路由。也就是定义了一个名为 demo 的 servlet ,对应 class 是net.mengkang.DemoServlet,访问的路由是/helloworld

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="true">

    <description>Servlet and JSP Examples.</description>
    <display-name>Servlet and JSP Examples</display-name>
    <request-character-encoding>UTF-8</request-character-encoding>

    <servlet>
      <servlet-name>demo</servlet-name>
      <servlet-class>net.mengkang.DemoServlet</servlet-class>
    </servlet>

    <servlet-mapping>
      <servlet-name>demo</servlet-name>
      <url-pattern>/helloworld</url-pattern>
    </servlet-mapping>

</web-app>

demo/WEB-INF/classes也就是上面 idea 编译出来的 classes 目录移过来的。那么最简单的 webapp 就算配置完成了,然后启动 tomcat

/Users/mengkang/Downloads 是我下载保存 tomcat 的目录

$ cd /Users/mengkang/Downloads/apache-tomcat-8.5.78/bin
$ chmod 755 *
$ ./startup.sh

访问下 http://localhost:8080/demo/helloworld 页面输出hello world,大功告成!

总结

tomcat 首先负责了 socket 的监听,然后根据目录去隔离管理各个webapp,在 webapp里面又配置 servlet 的定义和路由映射。就像我们在上一节中,web 服务器直接根据访问的路径找到对应的 cgi 程序一样。一个路由对应背后的一个 cgi 程序和 servlet 程序,就像 10 多年前的 php discuz 论坛,那时候还不流行单一入口,一个文件就是一个入口。而 spring 则改变了这模式,整个 spring 作为一个 servlet 接入到web 容器中,然后所有的路由在 servlet 本身里面去做分发。

当然 Servlet 的规范远不止于此,比如 filter 等

公众号回复 456 下载完整版 servlet 规范,有兴趣的可以瞟两眼,也可以作为手册备用。

原创博客,如需转载,请联系 i@mengkang.net
链接://mengkang.net/1514.html

👇 下面是我的公众号,高质量的博文我会第一时间同步到公众号,给个关注吧!

评论列表