Open TENCHIANG opened 4 years ago
JSP本质上也是Servlet,因为最终会编译成Servlet
javac \ -classpath tomcat/lib/servlet-api.jar \ -d ./classes/src/org/example/Hello.java
init()
destroy()
service()
Servlet不限定只能使用HTTP协议,所以单独拎出来
这就是为什么要覆写doGet、doPost等方法的原因(但别覆写HttpServlet.service本身),因为请求来时,会先判断是什么HTTP动词,然后再调用对应的方法(设计模式的Template Method模式)
protected void service (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String method = req.getMethod(); // 取得请求的方法 if (method.equals(METHOD_GET)) { // ... doGet(req, res); // ... } else if (method.equals(METHOD_POST)) { // ... doPost(req, res); // ... } else if (method.equals(METHOD_PUT)) { // ... } }
Servlet3.0(JavaEE6.0)之后,可以使用标注(Annotation)来告诉Web容器关于Servlet的一些信息,Servlet3.0之前用的是web.xml
@WebServlet("/hello") public class Hello extends HttpServlet { // ... }
只要Servlet上设置@WebServlet标注,容器就会自动读取其中的信息:如果请求的URI是/hello,则由Hello的实例提供服务。
@WebServlet( name="hello", // 指定Servlet的名称 默认为 类名 urlPatterns={"/hello"}, // 指定URI 默认为 /类名 loadOnStartup=1 // 程序启动时就初始化该Servlet类 默认为 -1 表示不会主动初始化 ) public class Hello extends HttpServlet { // ... }
Servlet类默认不会主动初始化(-1),只有在请求需要调用某个Servlet服务时,才将对应Servlet类载入、实例化、初始化,然后才真正的开始处理请求。 loadOnStartup如果设置大于-1的值,则表示程序启动后就初始化Servlet类。数字代表初始化的顺序,容器从较小的数字开始初始化,如果数字相同,容器实现厂商则可以自行规定(标准未定义)。
Servlet3.0(JavaEE6.0)之前,是在WebContent/WEB-INF/web.xml文件定义的(现在也可以)。
假设项目名为FirstServlet,在右边Project Explorer,展开项目根节点,右键Deployment Descriptor: FirstServlet节点,在弹出的菜单里点击Generate Deployment Descriptor Stub,就会生成web.xml,里面默认内容为:
FirstServlet
Project Explorer
Deployment Descriptor: FirstServlet
Generate Deployment Descriptor Stub
<?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_4_0.xsd" version="4.0"> <display-name>FirstServlet</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
这样的文件叫部署描述文件(Deployment Description, DD文件)。因为创建项目的时候,Dynamic web module version选择的是4.0(Servlet4.0),XSD文件为web-app_4_0.xsd,version为4.0。
Dynamic web module version
<display-name>代表Web应用程序的名称,Tomcat默认会使用应用程序目录(项目名)作为环境根目录(Context root)如localhost:8080/FirstServlet/,也可以在META-INF/context.xml中设置环境根目录。
<display-name>
META-INF/context.xml
用eclipse设置环境根目录:右键项目,选择Properties,在Web Project Settings中设置环境根目录。
Properties
Web Project Settings
Servlet4.0的<default-context-path>建议默认环境根目录:为啥叫建议,因为得考虑向下兼容,容器实现可以不理会这个设置。
<default-context-path>
web.xml可以覆盖Servlet中的标注,所以可以用标注做默认值,web.xml做更新值:
<servlet> <servlet-name>Hello</servlet-name> <servlet-class>org.example.Hello</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <serlvet-mapping> <servlet-name>Hello</servlet-name> <url-pattern>/helloUser</url-pattern> </serlvet-mapping>
如果<load-on-startup>数字相同,则按照在web.xml的书写顺序来初始化Servlet。
<load-on-startup>
<url-pattern>设置的逻辑名称(Logical Name)/helloUser覆盖了标注的/hello,所以必须得用/helloUser才能访问到该Servlet。
<url-pattern>
无论是标注还是xml,URI都只是逻辑名称,最终会由Web容器对应到实际处理请求的程序实体名称(Physical Name)或文件,甚至可以设置伪装后的名称,如/hello.jsp。
<servlet-name>:设置Servlet的名称 <servlet-class>:设置实体类名称(编译好的Servlet在WEB-INF/classes即可运行) <url-pattern>:设置逻辑名称
<servlet-name>
<servlet-class>
WEB-INF/classes
部署在Web容器上的文件组织与IDE开发环境下的不太一样, 要求把WEB-INF从WebContent中弄出来, 位于程序根目录下
再把整个项目放在tomcat的webapps文件下, 然后运行bin/startup命令启动就可以运行啦
实际上的部署会把项目打包成war(Web Archive)文件, 可以用JDK的jar命令来生成
cd FirstServlet jar cvf ../FirstServlet.war *
或者使用eclipse, 右键项目, Export, WAR file把项目导出成war文件. war文件本质就是打包好的zip文件, 放在tomcat/webapps目录下, 下次启动时, 容器检测到有war文件, 会将其解压, 并载入web程序
Export
WAR file
requestURI = contextPath + servletPath + pathInfo
HttpServletRequest.getRequestURI()
可以通过HttpServletRequest.getContextPath()获取
HttpServletRequest.getContextPath()
环境路径的设置在Servlet4.0之前没有规范,容器决定使用哪个Web应用程序(一个容器可部署多个)
如果环境路径 == 网站根目录:环境路径为空字符串
如果环境路径 != 网站根目录:环境路径以“/”开头,但不以“/”结尾
HttpServletRequest.getServletPath()
一旦决定是哪个是哪个Web应用程序来处理请求,接下来就是那个具体Servlet的事情了,Servlet必须设置URI模式:
$catalina/conf/web.xml
可以通过HttpServletRequest.getPathInfo()获取(注意:路径信息不包括请求参数)
HttpServletRequest.getPathInfo()
访问http://localhost:8080/FirstServlet/servlet/yy
http://localhost:8080/FirstServlet/servlet/yy
requestURI: /FirstServlet/servlet/yy contextPath: /FirstServlet servletPath: /servlet pathInfo: /yy
Servlet4.0中,HttpServletRequest新增了getHttpServletMapping()方法,可以取得javax.servlet.http.HttpServletMapping对象
HttpServletRequest
getHttpServletMapping()
javax.servlet.http.HttpServletMapping
HttpServletMapping对象
举个例子
Servlet学习笔记
JSP本质上也是Servlet,因为最终会编译成Servlet
Apache Tomcat Versions
手动编译Servlet
javax.servlet
init()
、destroy()
方法,提供服务时要调用的service()
方法等javax.servlet.http
Servlet不限定只能使用HTTP协议,所以单独拎出来
HttpServlet.service()
这就是为什么要覆写doGet、doPost等方法的原因(但别覆写HttpServlet.service本身),因为请求来时,会先判断是什么HTTP动词,然后再调用对应的方法(设计模式的Template Method模式)
@WebServlet:用标注定义Servlet
Servlet3.0(JavaEE6.0)之后,可以使用标注(Annotation)来告诉Web容器关于Servlet的一些信息,Servlet3.0之前用的是web.xml
只要Servlet上设置@WebServlet标注,容器就会自动读取其中的信息:如果请求的URI是/hello,则由Hello的实例提供服务。
@WebServlet还可以提供更多的信息
loadOnStartup
Servlet类默认不会主动初始化(-1),只有在请求需要调用某个Servlet服务时,才将对应Servlet类载入、实例化、初始化,然后才真正的开始处理请求。 loadOnStartup如果设置大于-1的值,则表示程序启动后就初始化Servlet类。数字代表初始化的顺序,容器从较小的数字开始初始化,如果数字相同,容器实现厂商则可以自行规定(标准未定义)。
用web.xml定义Servlet
Servlet3.0(JavaEE6.0)之前,是在WebContent/WEB-INF/web.xml文件定义的(现在也可以)。
用eclipse创建web.xml
假设项目名为
FirstServlet
,在右边Project Explorer
,展开项目根节点,右键Deployment Descriptor: FirstServlet
节点,在弹出的菜单里点击Generate Deployment Descriptor Stub
,就会生成web.xml,里面默认内容为:这样的文件叫部署描述文件(Deployment Description, DD文件)。因为创建项目的时候,
Dynamic web module version
选择的是4.0(Servlet4.0),XSD文件为web-app_4_0.xsd,version为4.0。<display-name>
代表Web应用程序的名称,Tomcat默认会使用应用程序目录(项目名)作为环境根目录(Context root)如localhost:8080/FirstServlet/,也可以在META-INF/context.xml
中设置环境根目录。用eclipse设置环境根目录:右键项目,选择
Properties
,在Web Project Settings
中设置环境根目录。Servlet4.0的
<default-context-path>
建议默认环境根目录:为啥叫建议,因为得考虑向下兼容,容器实现可以不理会这个设置。web.xml可以覆盖Servlet中的标注,所以可以用标注做默认值,web.xml做更新值:
如果
<load-on-startup>
数字相同,则按照在web.xml的书写顺序来初始化Servlet。<url-pattern>
设置的逻辑名称(Logical Name)/helloUser覆盖了标注的/hello,所以必须得用/helloUser才能访问到该Servlet。无论是标注还是xml,URI都只是逻辑名称,最终会由Web容器对应到实际处理请求的程序实体名称(Physical Name)或文件,甚至可以设置伪装后的名称,如/hello.jsp。
<servlet-name>
:设置Servlet的名称<servlet-class>
:设置实体类名称(编译好的Servlet在WEB-INF/classes
即可运行)<url-pattern>
:设置逻辑名称文件组织和部署
部署在Web容器上的文件组织与IDE开发环境下的不太一样, 要求把WEB-INF从WebContent中弄出来, 位于程序根目录下
再把整个项目放在tomcat的webapps文件下, 然后运行bin/startup命令启动就可以运行啦
实际上的部署会把项目打包成war(Web Archive)文件, 可以用JDK的jar命令来生成
或者使用eclipse, 右键项目,
Export
,WAR file
把项目导出成war文件. war文件本质就是打包好的zip文件, 放在tomcat/webapps目录下, 下次启动时, 容器检测到有war文件, 会将其解压, 并载入web程序URI模式设置
requestURI = contextPath + servletPath + pathInfo
requestURI
HttpServletRequest.getRequestURI()
获取contextPath(环境路径)
可以通过
HttpServletRequest.getContextPath()
获取环境路径的设置在Servlet4.0之前没有规范,容器决定使用哪个Web应用程序(一个容器可部署多个)
如果环境路径 == 网站根目录:环境路径为空字符串
如果环境路径 != 网站根目录:环境路径以“/”开头,但不以“/”结尾
servletPath(Servlet路径)
HttpServletRequest.getServletPath()
获取一旦决定是哪个是哪个Web应用程序来处理请求,接下来就是那个具体Servlet的事情了,Servlet必须设置URI模式:
$catalina/conf/web.xml
里面pathInfo(路径信息)
可以通过
HttpServletRequest.getPathInfo()
获取(注意:路径信息不包括请求参数)urlPatterns为"/servlet/*"的实例
访问
http://localhost:8080/FirstServlet/servlet/yy
HttpServletMapping
Servlet4.0中,
HttpServletRequest
新增了getHttpServletMapping()
方法,可以取得javax.servlet.http.HttpServletMapping
对象HttpServletMapping对象
举个例子