官方api文档:https://tomcat.apache.org/tomcat-8.0-doc/servletapi/index.html
Servlet和Tomcat的关系:一句话,Tomcat支持Servlet
Servlet是跟Tomcat关联在一起的,换而言之,Tomcat是哪个版本,就对应哪个版本的Servlet
需求:请用你现有的html,css,javascript,开发网站,比如可以让用户留言/购物/支付,你能搞定吗?
这就需要引入我们的动态网页(能和用户交互)技术===>Servlet
我们对之前的JavaWeb技术体系图进一步地细化:

Tomcat的web服务拿到一个请求后:
如果web服务发现是该请求是和java相关的,或者说是一个Servlet(动态请求,比如说可能会去操作数据库),那么Tomcat会去寻找Servlet,Servlet又去调用java程序,进行数据库操作
如果Tomcat的web服务发现请求的是一个静态资源,比如html,图片等,就直接拿到该资源,然后返回,不会和java程序或者数据库发生关系
因此我们说Tomcat其实是有两个功能的:一是充当Servlet的容器;二是充当普通的web服务
只支撑静态资源返回的还有apache,如果是一个静态资源的网站,不需要和数据库进行交互,其实完全可以使用Apache来作为web服务,或者只使用一个Nginx就可以了
什么是Servlet
Servlet在开发动态WEB工程中得到了广泛地应用,掌握好Servlet非常重要,Servlet是SpringMVC的基础
Servlet(java服务器小程序),它的特点有:
它是由服务器调用和执行的
即由tomcat解析和执行的
它是用java语言编写的,本质就是Java类
它是按照Servlet规范开发的(接口),Servlet本质就是一套接口规范
除了Tomcat可以去解析Servlet,weblogic也可以支持 Servlet,即只要按照规范去开发接口,就可以支持Servlet,类似于jdbc的接口规范
功能强大,几乎完成所有的网站功能
例子
需求说明:
http://localhost:8080/web应用名/helloServlet时,后台输出“hi HelloServlet”思路:
编写类HelloServlet去实现Servlet接口
实现service方法,处理请求,并响应数据
在web.xml中去配置Servlet程序的访问地址
首先创建web工程,配置好Tomcat

添加servlet-api.jar(在你安装的tomcat/lib下)到工程,因为servlet.jar不是jdk自带的,要引入才可以使用
在idea项目的web/WEB-INF下创建一个lib目录,将servlet-api.jar拷贝进去,然后右击jar包,点击add as library,在弹出的窗口中点击ok即可
在src包下面创建HelloServlet.java,并实现Servlet接口
package com.li.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* 1.开发一个servlet,需要实现Servlet接口
* 2.实现Servlet接口的方法:一共有5个
*/
public class HelloServlet implements Servlet {
/**
* 1.初始化 Servlet
* 2.当创建HelloServlet实例时,会调用init方法
* 3.该方法只会被调用一次
*
* @param servletConfig
* @throws ServletException
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init() 被调用");
}
/**
* 返回ServletConfig对象 也就是返回Servlet的配置
*
* @return
*/
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 1.service方法处理浏览器的请求(包括get/post)
* 2.当浏览器每次请求Servlet时,就会调用一次service方法
* 3.当Tomcat调用该方法时,会把http请求的数据封装成 实现了ServletRequest接口 的request对象
* 4.通过servletRequest对象,就可以得到用户提交的数据
* 5.servletResponse对象可以用于返回数据给Tomcat-->浏览器
*
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hi HelloServlet~");
}
/**
* 返回servlet的信息,使用较少
*
* @return
*/
@Override
public String getServletInfo() {
return null;
}
/**
* 1.该方法是在servlet被销毁时,被tomcat调用
* 2.只会调用一次
*/
@Override
public void destroy() {
}
}
实现了接口之后,在web.xml配置HelloServlet,即给HelloServlet提供对外的访问地址
目的是为了告诉Tomcat服务器,HelloServlet在哪里
<?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_4_0.xsd"
version="4.0">
<!--web.xml文件主要用来配置该web应用使用到的Servlet-->
<!--配置HelloServlet-->
<!--解读:
1.servlet-name:给Servlet取名(任意),该名字唯一
2.servlet-class:Servlet的类的全路径,Tomcat在反射生成该Servlet类实例时需要使用
3.servlet-mapping里的servlet-name要和上面的servlet-name保持一致
4.url-pattern:这个就是该Servlet访问的url的配置(路径)
5.这时我们应该这样访问Servlet:http://localhost:8080/web应用名/helloServlet
6.url-pattern的取名也是随意的(注意加上斜杠)
-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.li.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
</web-app>
设置 快捷键ctrl+/ 可以在当前位置注释,而不是在行
访问HelloServlet(记得要reploy或者restart)
可以自己配置快捷键启动
浏览器访问:
后台输出:可以看到init方法只调用了一次,而每次访问都会调用server方法
注意这里的第几次请求是值对于Tomcat而言,并不在乎是哪个浏览器
首先查询web.xml文件
看看请求的资源/helloServlet在web.xml有没有配置url-pattern
如果找到url-pattern,就会得到对应的servlet-name:HelloServlet
Tomcat维护了一个大的HashMap<id,Servlet>,查询该HashMap,看看有没有这个Servlet实例
如果没有查询到该servlet-name对应的id,即没有这个Servlet实例
就根据servlet-name去得到servlet-class:类的全路径
使用反射技术,将servlet实例化(同时调用init方法),并将该实例放入到Tomcat维护的HashMap<id,Servlet>中
首先查询web.xml文件
看看请求的资源/helloServlet在web.xml有没有配置url-pattern
如果找到url-pattern,就会得到对应的servlet-name:HelloServlet
Tomcat维护了一个大的HashMap<id,Servlet>,查询该HashMap,看看有没有这个Servlet实例
如果查询到,就直接调用该Servlet的service方法
结果处理
前面说到Servlet是单例的,现在来证明:
在实现的Servlet类HelloServlet中增加一个count属性
在service方法中,增加语句count++;并将其输出,如果每次输出的count是累加的,就说明每一次请求使用的都是同一个Servlet实例
使用浏览器访问:
后台输出:(在切换不同的浏览器访问后,count的值仍是累加的)
示意图
Servlet容器(比如Tomcat)加载Servlet,加载完之后,Servlet容器会创建一个Servlet实例并调用init()方法,init方法只会调用一次,Servlet容器在下面的情况装载Servlet
Servlet容器(如Tomcat)启动时自动装载某些servlet,实现这个需要在web.xml文件中添加
<load-on-startup>1</load-on-startup>
<!--1表示装载的顺序,比如在-->
在Servlet容器(如Tomcat)启动后,浏览器首次向Servlet发送请求
Servlet重新装载时(比如tomcat进行redeploy),浏览器再向Servlet发送请求的第1次
redeploy会销毁所有的Servlet实例
例子1:<load-on-startup>1</load-on-startup>
在web.xml文件中添加<load-on-startup>1</load-on-startup>之后,重新启动tomcat,可以看到,在没有浏览器发送请求的情况下,调用了init方法,这说明该Servlet已经被装载
例子2:Servlet重新装载时(比如tomcat进行redeploy),浏览器再向Servlet发送请求的第1次会装载Servlet
后台显示状况:

说明redeploy后Servlet实例被销毁了,当浏览器再次请求时,Tomcat会重新装载Servlet,因此init方法再次被调用
例子1:验证是否每收到一个http请求,服务器就会产生一个新的线程处理
在service方法中输出当前线程的id
浏览器请求Servlet时后台的输出:
当web应用被终止,或者Servlet容器终止运行,或者Servlet类重新装载时,会调用destroy方法(很少使用)
比如重启Tomcat,或者redeploy web应用
例子
在destroy方法中输出提示
重启Tomcat,在浏览器访问Servlet(让Servlet类加载),然后选择redeploy,可以看得destroy方法被调用了:
在浏览器再次请求Servlet,这次直接点击停止Tomcat服务,可以看到destroy方法也被调用了
运行bundleinstall后出现此错误:Gem::Package::FormatError:nometadatafoundin/Users/jeanosorio/.rvm/gems/ruby-1.9.3-p286/cache/libv8-3.11.8.13-x86_64-darwin-12.gemAnerroroccurredwhileinstallinglibv8(3.11.8.13),andBundlercannotcontinue.Makesurethat`geminstalllibv8-v'3.11.8.13'`succeedsbeforebundling.我试试gemin
我正在运行Ubuntu11.10并像这样安装Ruby1.9:$sudoapt-getinstallruby1.9rubygems一切都运行良好,但ri似乎有空文档。ri告诉我文档是空的,我必须安装它们。我执行此操作是因为我读到它会有所帮助:$rdoc--all--ri现在,当我尝试打开任何文档时:$riArrayNothingknownaboutArray我搜索的其他所有内容都是一样的。 最佳答案 这个呢?apt-getinstallri1.8编辑或者试试这个:(非rvm)geminstallrdocrdoc-datardoc-da
我有一个任务列表(名称、starts_at),我试图在每日View中显示它们(就像iCal)。deftodays_tasks(day)Task.find(:all,:conditions=>["starts_atbetween?and?",day.beginning,day.ending]end我不知道如何将Time.now(例如“2009-04-1210:00:00”)动态转换为一天的开始(和结束),以便进行比较。 最佳答案 deftodays_tasks(now=Time.now)Task.find(:all,:conditio
我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat
什么是0day漏洞?0day漏洞,是指已经被发现,但是还未被公开,同时官方还没有相关补丁的漏洞;通俗的讲,就是除了黑客,没人知道他的存在,其往往具有很大的突发性、破坏性、致命性。0day漏洞之所以称为0day,正是因为其补丁永远晚于攻击。所以攻击者利用0day漏洞攻击的成功率极高,往往可以达到目的并全身而退,而防守方却一无所知,只有在漏洞公布之后,才后知后觉,却为时已晚。“后知后觉、反应迟钝”就是当前安全防护面对0day攻击的真实写照!为了方便大家理解,中科三方为大家梳理当前安全防护模式下,一个漏洞从发现到解决的三个时间节点:T0:此时漏洞即0day漏洞,是已经被发现,还未被公开,官方还没有相
我目前有一个运行Ruby1.8.7和Rails2.3.2的RubyonRails项目我有一些从数据库中读取数据的单元测试,特别是两个连续项目的日期时间列,这两个项目应该相隔24小时。在一项测试中,我将项目2的日期时间设置为与项目1的日期时间相同。当我执行断言以确保两个值相等时,测试在rails2.3.2下工作正常。当我升级到rails2.3.11时,测试失败显示两次之间的差异将关闭并出现以下错误:expectedbutwas.这两个版本的rails中似乎存在浮点转换问题。如何解决float问题? 最佳答案 这也发生在我身上,我最终这
ruby1.9.3dev(2011-09-23修订版33323)[i686-linux]轨道3.0.20最近为什么在与DateTimeonRails相关的RSpecs项目上工作我发现在给定日期以下语句发出的值date.end_of_day.to_datetime和date.to_datetime.end_of_day虽然它们表示相同的日期时间,但比较时返回false。为了确认这一点,我打开了Rails控制台并尝试了以下操作1.9.3dev:053>monday=Time.now.monday=>2013-02-2500:00:00+05301.9.3dev:054>monday.cla
跳过联网激活:OOBE界面直接按Ctrl+Shift+F3进入审核模式。这样就可以直接进入系统进行一些硬件测试等,而不用联网激活导致新机无法退货。需要注意的是,在审核模式下进行的一些操作都会保留,并不会在退出后自动还原!安装的软件在正常开机进系统后还会看见!如果电脑确实没连互联网又不想强行跳过OOBE(网上很多教程会叫你直接结束OOBE进程,但这是不推荐的,因为一些厂商自带优化程序和系统初始化设置在后面都会应用,对于笔记本跳过的话你会发现驱动和内置应用都没有装上。其实这部分脚本就在系统盘的Recovery隐藏文件夹下),可以参考以下方式:https://www.landiannews.com/
在使用Rubyv2.2.2的ElCapitan(MacOSX10.11.1)上安装Rails时,出现以下错误:ERROR:Errorinstallingnokogiri:ERROR:Failedtobuildgemnativeextension./Users/jon/.rvm/rubies/ruby-2.2.2/bin/ruby-r./siteconf20151117-26799-ux15fd.rbextconf.rb--use-system-librariescheckingiftheCcompileraccepts...***extconf.rbfailed***Couldnotc
标题说明了一切。请注意,这不是模型或初始值设定项的更改。我可以删除Controller中的一个实例变量(例如,@user),然后重新加载一个View,它会工作-直到我重新启动服务器,在这种情况下它会提示变量为nil。我正常工作,然后切换到一组完全不同的Controller和View上工作,现在它无缘无故地发生了。应用处于开发环境中。development.rb内容:Dashboard::Application.configuredoconfig.cache_classes=falseconfig.whiny_nils=trueconfig.consider_all_requests_l