深入了解tomcat中servlet的创建方式实现_Tomcat

来源:脚本之家  责任编辑:小易  

用eclipse创建web工程时把如下勾上,追问加下我qq好吗,如果不会配置环境2113变量,建议5261先用Myecilipse,先编译出class文件,然后在tomcat底下4102的webapps文件夹下放入装有1653(WEB-INF(xxx.jsp)和xxx.html和class文件夹(装有class文件),),首先,开发工具应该用myeclipse,这是企业开发用的版本,找到你的tomcat安装路径,你是新手建议你用myeclipse 因为myeclipce创建项目的时候会自带创建的web.xml文件 如果你不想换编译器 那就只能自己在web-inf文件夹里面创建web.xml文件了追问web-inf在哪里我换了tomcat6追答和tomcat没有关系 webinf在你的项目文件夹下,用myeclipse更好,用tomcat5或者6试试www.zgxue.com防采集请勿采集本网。

一、 什么是servlet

ServletContext : 每一个web应用都有一个 ServletContext与之相关联。 ServletContext对象在应用启动的被创建,在应用关闭的时候被销毁。 ServletContext在全局范围内有效,类似于应用中的一个全局变量。 ServletContextListener: 使用listener

1.1、用官方的话解释:

E:\Tomcat 5.0\webapps\ 在这个目录下新建个文件夹(工程名随便起),不要用系统默认的那个ROOT 然后在这个文件夹中建立一个WEB-INF(必须大写)文件夹,然后在WEB-INF中建立文件夹classes,和web.xml文件把写好的class文件放在classes中 配置web.xml x

Servlet是oracle公司提供的一门用于开发动态web资源的技术,属于javaEE体系中的一种核心规范。

说白了就是想当容器启动时拉起一些服务呗,可以这么搞:(1)新建一个Servlet实现ServletContextListener接口,重写contextInitialized用来执行启动时要做的事情,例子中我拉起了一个线程,或者重写contextDestroyed方法来执行容器销毁时要做什

通俗解释一下:就是我们开发人员所编写的一个类,必须直接或者间接实现这个javaEE的核心规范,也就是实现Servlet接口,因为这种类产生的对象可以被浏览器访问到,因此称之为Servlet,并且javaEE中规定了只有Servlet的实现类产生的对象才可以被浏览器访问,就是Servlet.(也就是说这个类要直接或者间接实现了Servlet接口)

tomcat访问所有的资源,都是用Servlet来实现的。 在Tomcat看来,资源分3种 1. 静态资源,如css,html,js,jpg,png等 2. Servlet 3. JSP 对于静态资源,Tomcat最后会交由一个叫做DefaultServlet的类来处理 对于Servlet ,Tomcat最后会交由一个叫做

二、开始进入servlet的创建

应该是tomcat里创建响应的socketServer线程类接收请求连接,然后在再创建或引用对应的servlet实例来处理请求连接。servlet是单例的,只创建一次。所以最好不要使用serlvet中的实例字段。。

2.1、通过前面介绍,我们知道了一个什么样的类创建的对象可以被浏览器访问,首先我们直接上代码:

package com.briup.web;import java.io.IOException;import javax.servlet.Servlet;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class FirstWay implements Servlet {public FirstWay() {System.out.println("对象创建了");}@Overridepublic void init(ServletConfig config) throws ServletException {// TODO Auto-generated method stubSystem.out.println("我是init:我被调用了");}@Overridepublic ServletConfig getServletConfig() {// TODO Auto-generated method stubreturn null;}@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {// TODO Auto-generated method stubSystem.out.println("我是service,我被调用了");}@Overridepublic String getServletInfo() {// TODO Auto-generated method stubreturn null;}@Overridepublic void destroy() {// TODO Auto-generated method stubSystem.out.println("我是destory:我被调用了");}}

那么,一个满足servlet的类已经创建好了,接下来抛出疑问

servet对象由谁创建?

里面实现的接口方法,哪些会调用,什么时候调用,调用几次?

第一个疑问: 既然是servlet类,由我们开发人员自己手动创建对象,显然是不合理,所以这个对象的创建,是交给tomcat创建的,我们开发人员只需要告诉 tomcat,让他创建,让他什么时候创建就行了;

如何告诉?

1、方法一:通过配置webxml的方式。(极其不推荐使用)

对于整个动态web项目而言,web.xml是最先加载的配置文件,所以在web.xml的方式配置

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>firstWay</display-name> <servlet> <servlet-name>FirstWay</servlet-name> <servlet-class>com.briup.web.FirstWay</servlet-class> <!-- <load-on-startup>1</load-on-startup> --> </servlet> <servlet-mapping> <servlet-name>FirstWay</servlet-name> <url-pattern>/FirstWay</url-pattern> </servlet-mapping></web-app>

解释:

1、servlet-name:见名知意:servlet的名字,注意要与下面你设置映射的名字对应

2、serlvet-class:serlvet的全限定名

3、load-on-startup:是否在tomcat启动的时候就创建servlet对象,传入一个大于0的整数‘'(默认是浏览器第一次请求的时候创建servlet对象

4、servlet-mapping:见名知意,设置浏览器的访问映射

5、servlet-name:于上面的对应

6、url-pattern:浏览器的访问映射(假设默认是本机的话,且tomcat的端口号为8080,那么浏览器访问这个servlet的路径为:localhost:8080/项目名/FirstWay

有了这些基础,让我们访问看看;

第一步:启动tomcat

在这里插入图片描述

tomcat正常启动

第二步:通过浏览器访问(我们这里手动访问3次)

在这里插入图片描述

浏览器访问正常

第三步:观察控制台

在这里插入图片描述 

通过运行结果分析:

第一次启动服务器,对象并没有被创建

浏览器请求三遍,但是对象只创建一次,init()方法也只调用一次

每访问一次,对象便会调用一次service()方法

其他方法没被调用

解释为嘛没被调用:getServletConfig():得到ServletConfig对象

: getServletInfo():得到Servlet的信心,比如作者

:destroy():servlet销毁的时候才会调用这个方法,(比如:tomcati正常关闭 这里我就不去测试,想测试的小伙伴,可以右键service,点击stop)然后再观察控制台便可知了。

 2、方法二:注解的方式告诉tomcat(与前者相比,推荐使用)

@WebServlet(value ="映射路径")public Fristservlet implement Servelt {}

通过这个注解也可以设置,是否在启动服务器的时候就创建对象,这里就不演示了,

注意:(一旦使用了注解的方式告诉tomcat如果创建某个对象,就不能在web.xml里面再对这个servlet进行访问设置了

三、回归主题,servlet的第二种创建方式

有了前面的解释,直接上代码然后再分析

package com.briup.web;import java.io.IOException;import javax.servlet.GenericServlet;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.annotation.WebServlet;@WebServlet(value = "/secondWay")public class SecondWayCreate extends GenericServlet {@Overridepublic void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {// TODO Auto-generated method stubSystem.out.println("调用了service方法");}}

1、比第一种方法简洁,实现的是GenericServlet这个类

2、我们看一下GenericServlet源码,然后进行分析;

public abstract class GenericServlet implements Servlet, ServletConfig,

可知,这是个抽线类,是servlet接口的实现类,那么GenericServlet间接 实现了servlet接口,

与第一种方式相比:开发者不是必须将一些接口中不必要的方法实现,可以具有选择性,减少了代码量。然而并没有上面ruan用,就是装b而已

三、重点第三种方式(与前两者相比,我更推荐第三种方式)

直接上代码

package com.briup.web;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet(value = "/ThreeWayCreate")public class ThreeWayCreate extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stubsuper.doGet(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stubsuper.doPost(req, resp);}}

通过以上代码,可能就有小伙伴要问了

不是说servlet要直接或者间接实现servlet接口吗,不是说浏览器每请求一次就要调用一次service方法吗?方法在哪呢?这不是与前面理论冲突了吗?

我们继续看源码,源码才是道理

我在下面值列举源码里面比较核心的部分,需要理解更加深入了解的小伙伴,直接去看源码,tomcat是开源的

package com.briup.web;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet(value = "/ThreeWayCreate")public class ThreeWayCreate extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stubsuper.doGet(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// TODO Auto-generated method stubsuper.doPost(req, resp);}}

分析:

第一步分析

在这里插入图片描述

可知这个抽象类继承了GennericeServlet这个抽象类 也就是逐层往下推,实现了Servle接口,那么这个抽线类必然也继承了serice方法。

第二步分析

在这里插入图片描述

这个是继承servlet接口的service方法,当浏览器每请求一次时,都会调用这个方法,由图可知,这个方法已经被HttpServlet实现了,由实现类可以得出,请求对象req,和响应对象res,被强转成了HttpServletRequest,和HttpServletResponse(向下转型),然后将强转的对象,传入HttpServlet重载的Service方法中,调用,第三步,分析重载后的Service(HttpRequest req,HttpRespone res);

第三步分析

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 logic doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); } catch (IllegalArgumentException iae) { // Invalid date header - proceed as if none was set ifModifiedSince = -1; } if (ifModifiedSince < (lastModified / 1000 * 1000)) { // 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 less maybeSetLastModified(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); } }

通过传过来的HttpRequest对象,判断请求方式,通过请求方式,决定调用哪个方法(如果请求方式是post方式,那么就会调用doPost(HttpRequest req,HttpRestpone Res)方法

第四步分析

综上分析,总结:tomcat创建对象,当浏览器请求的时候,调用Servlet的Service(ServeltRequest req,ServletRespone res )方法,然后这个方法再调用,HttpServlet里面重载的Servlet(HttpServletReqeust req ,HttpServletRespone res)方法,然后这个方法会通过请求方式是什么,选择性的调用doPost(),还是doGet()方法(当然还有很多其他的方式这里就不列举了), 因此第三种方式,的本质还是当浏览器发起一次请求的时候调用了Servlet接口里面的Service(ServeltRequest req,ServletRespone res )方法,然后通过实现类的里面的逻辑,间接的调用了doPost()等方法。

优点:

1、通过请求方式可以处理相应的请求,使得逻辑更加清晰

2,减少代码量,是程序更加简洁

3,使得请求或者响应的操作性更加丰富

4…

四、 总结:

注意点:浏览器发起请求调用的一定是servlet种的service方法;

到此这篇关于深入了解tomcat中servlet的创建方式实现的文章就介绍到这了,更多相关tomcat servlet创建方式内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网! 您可能感兴趣的文章:tomcat关于配置servlet的url-pattern的问题思路详解Spring关闭Tomcat Servlet容器时内存泄漏问题解决方案详解Tomcat是如何实现异步Servlet的详解如何通过tomcat的ManagerServlet远程部署项目servlet和tomcat_动力节点Java学院整理Tomcat怎么实现异步Servlettomcat中Servlet对象池介绍及如何使用tomcat中Servlet的工作机制详细介绍

有时Servlet在生成响应报文前必须2113等待某些耗时的操5261作,比如在等待4102一个可用的JDBC连接或等待一1653个远程Web服务的响应。对于这种情况servlet规范中定义了异步处理方式,由于Servlet中等待阻塞会导致Web容器整体的处理能力低下,所以对于比较耗时的操作可以放置到另外一个线程中进行处理,此过程保留连接的请求和响应对象,在处理完成之后可以把处理的结果通知到客户端。下面先看Servlet在同步情况下的处理过程,如图所示,Tomcat的客户端请求由管道处理最后会通过Wrapper容器的管道,这时它会调Servlet实例的service方法进行逻辑处理,处理完后响应客户端,整个处理由Tomcat的Executor线程池的线程处理,而线程池的最大线程数使有限制的,所以这个处理过程越短、越快把线程让回线程池就越好。但如果Servlet中的处理逻辑耗时越长就会导致长期地占用Tomcat的处理线程池,影响Tomcat的整体处理能力。为了解决上面的问题引入了支持异步的Servlet,同样是客户端请求到来,然后通过管道最后进入到Wrapper容器的管道,调用Servlet实例的service后,创建一个异步上下文将耗时的逻辑操作封装起来,交给用户自己定义的线程池,这时Tomcat的处理线程就能马上回到Executor线程池,而不用等待耗时的操作完成才让出线程,从而提升了Tomcat的整体处理能力。这里要注意的是,由于后面做完耗时的操作后还需要对客户端响应,所以需要保持住Request和Response对象,以便输出响应报文到客户端。再结合一个简单的异步代码来看Tomcat对Servlet异步的实现:public class AsyncServlet extends HttpServlet {ScheduledThreadPoolExecutor userExecutor = new ScheduledThreadPoolExecutor(5);public void doGet(HttpServletRequest req, HttpServletResponse res) {AsyncContext aCtx = req.startAsync(req, res);userExecutor.execute(new AsyncHandler(aCtx));}}public class AsyncHandler implements Runnable {private AsyncContext ctx;public AsyncHandler(AsyncContext ctx) {this.ctx = ctx;}@Overridepublic void run() {//耗时操作PrintWriter pw;try {pw = ctx.getResponse().getWriter();pw.print("done!");pw.flush();pw.close();} catch (IOException e) {e.printStackTrace();}ctx.complete();}}我们创建一个AsyncServlet,它定义了一个userExecutor线程池专门用于处理该Servlet的所有请求的耗时的逻辑操作。这样就不会占用Tomcat内部的Executor线程池,影响到对其他Servlet的处理。这种思想有点像资源隔离,耗时的操作统一由指定的线程池处理,而不要影响其它耗时少的请求处理。Servlet的异步的实现就很好理解了,startAsync方法其实就是创建了一个异步上下文AsyncContext对象,该对象封装了请求和响应对象。然后创建一个任务用于处理耗时逻辑,后面通过AsyncContext对象获得响应对象并对客户端响应,输出“done!”。完成后要通过complete方法告诉Tomcat内部我已经处理完,Tomcat就会请求对象和响应对象进行回收处理或关闭连接内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • tomcat服务配置和自启动详解
  • 详解将web项目war包部署到tomcat服务器基本步骤
  • tomcat中的session与cookie深入讲解
  • 简单实现nginx+tomcat的反向代理与动静分离
  • web项目打成war包部署到tomcat时报mysql access denied for user
  • tomcat 发布程序使用cmd查看端口占用、相应进程、杀死进程等的命
  • 浅谈tomcat乱码与端口占用的解决方案
  • linux下安装配置tomcat
  • 详解windows下调整tomcat启动参数的实现方法
  • 关于给tomcat设置maxpostsize的问题及注意事项
  • Tomcat中的Servlet异步是怎么实现的
  • 我是java新手 tomcat7中怎样进行servlet的配置
  • 请问如何打开tomcat中默认使用类名访问servlet的方法
  • servlet与Tomcat的关系
  • servlet在tomcat启动时如何执行特定的类
  • 怎样在tomcat中部署编译好的servlet?
  • 小弟我在ECLIPSE中创建了一个TOMCAT下的SERVLET为...
  • tomcat中对静态资源的访问也会用servlet来处理吗
  • Tomcat Servlet 多线程到底是怎么实现的?
  • tomcat编译jsp之后生成的Servlet书上说放在tomcat7...
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全星外虚拟主机华众虚拟主机linuxwin服务器ftp服务器dns服务器tomcat nginxzabbix云和虚拟化服务器其它首页服务器tomcat关于配置servlet的url-pattern的问题思路详解spring关闭tomcat servlet容器时内存泄漏问题解决方案详解tomcat是如何实现异步servlet的详解如何通过tomcat的managerservlet远程部署项目servlet和tomcat_动力节点java学院整理tomcat怎么实现异步servlettomcat中servlet对象池介绍及如何使用tomcat中servlet的工作机制详细介绍tomcat服务配置和自启动详解详解将web项目war包部署到tomcat服务器基本步骤tomcat中的session与cookie深入讲解简单实现nginx+tomcat的反向代理与动静分离web项目打成war包部署到tomcat时报mysql access denied for usertomcat 发布程序使用cmd查看端口占用、相应进程、杀死进程等的命浅谈tomcat乱码与端口占用的解决方案linux下安装配置tomcat详解windows下调整tomcat启动参数的实现方法关于给tomcat设置maxpostsize的问题及注意事项tomcat7.0安装配置详细(图文)直接双击启动tomcat中的startup.tomcat中更改网站根目录和默认页在tomcat中部署web项目的操作方法关于tomcat的server.xml里host节如何修改tomcat默认端口号8080的tomcat环境变量详细配置步骤windows下配置两个或多个tomcat启window7下tomcat7.0安装配置方法启动tomcat时 错误: 代理抛出异常非常实用的tomcat启动脚本实现方法linux下定时切割mongodb数据库日志并删除docker安装tomcat 404问题的解决方案tomcat整体结构简单介绍tomcat 多站点配置详解及实现方法在同一台服务器上配置多个tomcat的方法tomcat 5.5 数据库连接池配置tomcat默认程序发布路径的使用与修改方法tomcat 几种连接池配置代码(包括tomcat5tomcat下载安装并部署到idea的教程(附带
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved