Tomcat与Servlet(2)

发布于:2025-04-18 ⋅ 阅读:(20) ⋅ 点赞:(0)

上篇文章:

Tomcat与Servlethttps://blog.csdn.net/sniper_fandc/article/details/147278469?fromshare=blogdetail&sharetype=blogdetail&sharerId=147278469&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link        上篇文章介绍了Tomcat服务器的启动和基本程序的部署,但是在开发环境下,如果修改代码,就需要重复打包部署的步骤,有点繁琐,因此在开发阶段,我们有更简洁的流程(这个流程还比不上使用SpringBoot框架,属于折中方案):

目录

1 简化流程

1.1 安装Smart Tomcat

1.2 配置Smart Tomcat

1.3 Tomcat底层原理


1 简化流程

1.1 安装Smart Tomcat

        上述操作如果开发人员每修改一次代码,就需要重新打包部署一次,非常麻烦,这里可以使用插件Smart Tomcat来简化打包部署的流程。

        在Setting界面找到插件安装,搜索Smart Tomcat插件安装即可。

        注意:Smart Tomcat不等于Tomcat,即它只是一个插件,不是HTTP服务器。Smart Tomcat在背后所做的工作就是让我们不用再打开Tomcat目录使用命令启动,可以在IDEA中点击自动启动Tomcat,并且自动部署运行我们的web程序。

1.2 配置Smart Tomcat

        打开Configurations(在右上角运行左侧),点击加号添加Smart Tomcat。

        Name表示为当前服务起名。

        Tomcat server表示Tomcat的安装路径,首次使用时需要设置。

        Deployment directory对应项目中的webapp的路径。

        Use classpath of module和Context path表示浏览器输入的一级URL(在IP和端口后申请访问的资源)。

        Server port表示Tomcat服务器的端口。

        Admin port表示Tomcat的管理端口(比如控制重启等)。

        配置完成后,点击运行,即可自动编译、打包、部署、运行。

        见到如上信息,就说明成功启动了,也可以访问我们的程序了。如果修改了代码,重新运行程序即可。

        注意:Smart Tomcat并没有把war包部署到Tomcat的webapps目录下,而是直接通过让Tomcat读取项目中target目录下编译好的文件,运行.class文件来运行项目。

1.3 Tomcat底层原理

        这里给出伪代码:

class Tomcat {

// 用来存储所有的 Servlet 对象

    private List<Servlet> instanceList = new ArrayList<>();

    public void start() {

        // 根据约定,读取 WEB-INF/web.xml 配置文件;

        // 并解析被 @WebServlet 注解修饰的类

        // 假定这个数组里就包含了我们解析到的所有被 @WebServlet 注解修饰的类.

        Class<Servlet>[] allServletClasses = ...;

        // 实例化出所有的 Servlet 对象出来;

        for (Class<Servlet> cls : allServletClasses) {

          // 利用 java 中的反射特性

          // 实际上涉及一个类的加载问题,因为类字节码文件是按照约定

          // 方式(全部在WEB-INF/classes文件夹下)存放的,所以tomcat内部

          // 实现了一个自定义的类加载器(ClassLoader)用来负责这部分工作。

          Servlet ins = cls.newInstance();

          instanceList.add(ins);

        }

        // 调用每个 Servlet 对象的init()方法,这个方法在对象的生命中只会被调用这一次;

        for (Servlet ins : instanceList) {

          ins.init();

        }

        // 启动一个 HTTP 服务器

        // 并用线程池的方式分别处理每一个Request

        ServerSocket serverSocket = new ServerSocket(8080);

        // 实际上 tomcat 不是用的固定线程池,这里只是为了说明情况

        ExecuteService pool = Executors.newFixedThreadPool(100);

        while (true) {

            Socket socket = ServerSocket.accept();

            // 每个请求都是用一个线程独立支持,这里体现了Servlet是运行在多线程环境下的

            pool.execute(new Runnable() {

                doHttpRequest(socket);

            });

        }

        // 调用每个 Servlet 对象的 destroy() 方法,这个方法在对象的生命中只会被调用这一次;

        for (Servlet ins : instanceList) {

            ins.destroy();

        }

}

// 内置main方法

    public static void main(String[] args) {

        new Tomcat().start();

    }

}

        这里的doHttpRequest(Socket socket)方法根据请求构造出HttpServletRequest对象,根据URL判断寻找的资源是静态资源还是动态资源,如果是静态资源直接返回对应的资源即可;如果是动态资源就找到Servlet对象,调用其中的service()方法,service()方法就会判断这次请求方法是GET还是POST或者其他,指定对应的doXXX方法。

        注意:doXXX方法是多态的体现,我们开发人员写的类继承HttpServlet类(有doXXX系列的方法,需要我们的自定义类重写),而HttpServlet类继承Servlet类,而在动态资源的访问中引用对象的类型是Servlet,因此相当于我们通过父类引用Servlet来调用子类的doXXX方法(父类引用指向子类对象)。

下篇文章:

Servlethttps://blog.csdn.net/sniper_fandc/article/details/147279226?fromshare=blogdetail&sharetype=blogdetail&sharerId=147279226&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link


网站公告

今日签到

点亮在社区的每一天
去签到