韩老师学生
- 官网文档
- 为什么会出现Servlet
- 什么是Servlet
- Servlet在JavaWeb项目位置
- Servlet基本使用
- Servlet开发方式说明
- 快速入门- 手动开发 servlet
- 浏览器请求Servlet UML分析
- Servlet生命周期
- GET和POST请求分发处理
- 通过继承HttpServlet开发Servlet
- IDEA配置Servlet
- Servlet注意事项和细节
- Servlet注解方式
- 快速入门
- 注解详解
- initParams
- Servlet urlPattern 配置
- 精准匹配
- 目录匹配
- 扩展名匹配
- 任意匹配
- 注解注意事项
官网文档
官网文档: https://tomcat.apache.org/tomcat-8.0-doc/servletapi/index.html
离线文档
JAVA_EE_api_中英文对照版
●Servlet和Tomcat的关系: 一句话, Tomcat支持Servlet
为什么会出现Servlet
1.提出需求: 请用你现有的html css javascript
, 开发网站, 比如可以让用户留言/购物/支付, 你能搞定吗?
2.引入我们动态网页(能和用户交互)技术 ⇒ Servlet
3.对Java Web
技术体系的流程图改造说明(细化).[整体的概念]
什么是Servlet
Servlet
在开发动态WEB
工程中, 得到广泛的应用. 掌握好Servlet
非常重要, Servlet
(基石)是SpringMVC
的基础
●Servlet
(java
服务器小程序), 它的特点:
1.它是由服务器端调用和执行的(一句话: 是Tomcat
解析和执行)
2.它使用java
语言编写的, 本质就是Java
类
3.它是按照Servlet
规范开发的(除了tomcat->Servlet weblogic->Servlet
)
4.功能强大, 可以完成几乎所有的网站功能(在以前, 老程序员, 使用Servlet
开发网站) 技术栈要求高, 内卷(硬起来)
Servlet在JavaWeb项目位置
Servlet基本使用
Servlet开发方式说明
1.servlet3.0
前使用web.xml
, servlet3.0
版本以后(包括3.0
)支持注解, 同时支持web.xml配置
2.如何查看servlet
版本[如图]
3.讲解SpringBoot
时, 我们用注解方式, 从ssm, springboot
后面全部使用注解
4.这里专门讲servlet
, 为让大家更清晰地知道servlet
使用原理, 我们用配置方式(说明, 原生的Servlet
在项目中使用很少)
5.不管使用哪种方式, 本质都一样
快速入门- 手动开发 servlet
需求说明
1.开发一个HelloServlet
2.当浏览器 访问 http://localhost:8080/web应用名/helloServlet
时, 后台输出 hi HelloServlet
●具体步骤
1.编写类HelloServlet
去实现Servlet
接口
2.实现service
方法, 处理请求, 并响应数据
3.在web.xml
中去配置servlet
程序的访问地址
1.创建servlet Java Web
工程, 并配置好Tomcat
. IDEA开发部署JavaWeb工程
2.添加servlet-api.jar
(在tomcat/lib
下) 到工程, 因为servlet.jar
不是jdk
自带的, 要引入
3.在src目录
com.zzw.servlet
包下新建HelloServlet.java
, 并实现Servlet
接口
package com.zzw.servlet;
import javax.servlet.*;
import java.io.IOException;
/**
* @author 赵志伟
* @version 1.0
* 1.开发一个Servlet需要实现Servlet接口
* 2.实现Servlet接口的五个方法
*/
@SuppressWarnings({"all"})
public class HelloServlet implements Servlet {
private int count;
/**
* 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 {
//如果count的值在不停地累积, 说明HelloServlet是单例的
System.out.println("hi HelloServlet~, count=" + count++);
}
/**
* 返回servlet的信息,使用较少
* @return
*/
@Override
public String getServletInfo() {
return null;
}
/**
* 1.该方法是在servlet被销毁时,调用
* 2.只会调用一次
*/
@Override
public void destroy() {
}
}
web.xml注释时发现前面有空格
解决方案 Settings->Editor->Code Style->XML, 取消勾选
IDEA配置快捷键: settings->Keymap
重启(Alt+R)选择重新部署,速度快, 不要选Restart server, 这样会把JDK都重启, 速度很慢
- 在web.xml文件中配置由Tomat访问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-->
<!--
1.servlet-name: 给Servlet取名(由程序员决定), 这个名字是不能重复取的
2.servlet-class:该Servlet的类的全路径, Tomcat在反射生成Servlet时需要使用
3.url-pattern: 这个就是访问该Servlet的url地址
这时我们可以这样访问:http://localhost:8080/servlet/helloServlet
4.url-pattern 访问地址是由程序员决定的
5.load-on-startup 表示在tomcat 启动时, 会自动地加载servlet实例
小技巧: alt+R -> Redeploy选择重新部署, 速度更快
-->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.zzw.servlet.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
</web-app>
浏览器请求Servlet UML分析
Servlet生命周期
●主要有三个方法
1.init方法
2.service方法
3.destroy方法
●初始化阶段
Servlet
容器(比如:Tomcat
) 加载Servlet
, 加载完成后, Servlet
容器会创建一个Servlet
实例并调用init
方法(创建的实例放入HashMap), init
方法只会调用一次, Servlet
容器在下面的几种情况下会装载Servlet
:
1.Servlet
容器(比如: Tomcat
)启动时自动装载某些servlet
, 实现这个需要在web.xml
文件中添加
<load-on-startup>1</load-on-startup> 1
表示装载的顺序
2.在Servlet
容器启动后, 浏览器首次向Servlet
发送请求
3.Servlet
重新装载时(比如tomcat
进行redeploy
【redeploy
会销毁所有的Servlet
实例】), 浏览器再向Servlet
发送请求的第1
次
●处理浏览器请求阶段(service
方法)
1.每收到一个http
请求, 服务器就会产生一个新的线程处理[线程]
2. 创建一个用于封装HTTP
请求消息的ServletRequest
对象和一个代表HTTP
响应消息的ServletResponse
对象
3. 然后调用Servlet
的service()
方法并将请求和响应对象, 作为参数传递进去
●终止阶段(destroy
方法)(体现Servlet
完整的生命周期)
当web
应用被终止, 或者Servlet
容器终止运行, 或者Servlet
类重新装载时, 会调用destroy()
方法, 比如重启tomcat
, 或者 redeploy web
应用
GET和POST请求分发处理
●开发Servlet
, 通常编写doGet, doPost
方法, 来对表单的get
和post
请求进行分发处理
●代码演示
1.web路径
下新建register.html
<body>
<h1>注册用户</h1>
<form action="http://localhost:8080/servlet3/helloServlet" method="post">
u: <input type="text" name="username"/><br/>
<input type="submit" value="注册用户"/>
</form>
</body>
2.修改HelloServlet
的service
方法完成分发请求
/**
* 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 {
//如果count的值在不停地累积, 说明HelloServlet是单例的
System.out.println("hi HelloServlet ~~count="+ ++count);
//Tomcat每处理一次http请求, 就生成一个新的线程
System.out.println("当前线程id=" + Thread.currentThread().getId());
//思考->从servletRequest对象来获取请求方式
//1.ServletRequest 没有得到提交方式的方法
//2.ServletRequest 看看ServletRequest子接口有没有相关方法
//3.老师小技巧: ctrl+alt+b 可以看到接口的子接口和实现子类
//4.把servletRequest转成 HttpServletRequest引用
//5.仍然是Java基础的OOP
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String method = httpServletRequest.getMethod();
System.out.println("method=" + method);//method=GET 大写的
if ("GET".equals(method)) {
doGet();//用doGet() 处理GET请求
} else if ("POST".equals(method)) {
doPost();//用doPost() 处理POST请求
}
}
/**
* 用于响应get请求
*/
public void doGet() {
System.out.println("HelloServlet doGet()...");
}
/**
* 用于响应post请求
*/
public void doPost() {
System.out.println("HelloServlet doPost()...");
}
3.测试…
通过继承HttpServlet开发Servlet
●HttpServlet介绍
在实际项目中, 都是使用继承 HttpServlet 类来开发 Servlet 程序, 更加方便
●HttpServlet类图如下
●Http介绍
1.通过继承HttpServlet开发一个HiServlet
2.当浏览器 访问 http://localhost:8080/web应用名/hiServlet时,后台输出hi HiServlet
●具体的开发步骤
1.编写一个类去继承 HttpServlet类
2.根据业务需要重写doGet 或 doPost 方法
3.到 web.xml 中配置 Servlet程序
1.com.zzw.servlet
包下新建HiServlet
public class HiServlet extends HttpServlet {
//重写HttpServlet的doGet 和 doPost
//alt + insert
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HiServlet doGet()...");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HiServlet doPost()...");
}
}
2.配置web.xml
<!--配置HiServlet-->
<servlet>
<servlet-name>HiServlet</servlet-name>
<servlet-class>com.zzw.servlet.HiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HiServlet</servlet-name>
<url-pattern>/hiServlet</url-pattern>
</servlet-mapping>
IDEA配置Servlet
在WEB-INF目录下的lib文件夹下导入servlet-api.jar包并且Add As Library后右键才有新建Servlet的选项
会自动生成Servlet类和web.xml配置
public class OkServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//可以写自己的业务处理代码
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//可以写自己的业务处理代码
}
web.xml自动生成以下半截代码, 这里需要手动配置url-pattern
Servlet注意事项和细节
- Servlet是一个供其它Java程序(Servlet)引擎调用的Java类, 不能独立运行
- 针对浏览器的多次Servlet请求, 通常情况下, 服务器只会创建一个Servlet实例对象, 也就是说Servlet实例对象一旦创建, 它就会驻留在内存中,存在于Tomcat维护的HashMap中, 为后续的其他请求而服务, 直至web容器退出/或者redeploy该web应用, servlet实例对象才会销毁, 从HashMap中移除
- 在Servlet的整个生命周期中,init方法只被调用一次, 而对每次请求都导致Servlet引擎调用一次servlet的service方法
- 对于每次访问请求, Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象, 然后将这两个对象作为参数传递给它调用的Servlet的service()方法, service方法再根据请求方式分别调用doGet()方法和doPost()方法
- 如果在<servlet>元素中配置了一个<load-on-startup>元素, 那么web应用程序在启动时, 就会装载并创建Servlet的实例对象, 以及调用Servlet实例对象的init()方法
Servlet注解方式
快速入门
省去了在web.xml配置的麻烦
方法外不能使用.var
/**
* 显示方法之间的分割线 Editor->General->Appearance->Show method separators
* 1.@WebServlet是一个注解
* 2.@WebServlet的源码
* 3.urlPatterns 对应web.xml中的 <url-Pattern></url-Pattern>
* {"/ok1", "/ok2"} 可以给OkServlet配置多个 urlPattern
* 相当于这个@WebServlet(urlPatterns={"/ok1", "/ok2"}) 代替了web.xml的配置
* 4.浏览器可以这样访问OkServlet: http://localhost:8080/servlet/ok1 或者 http://localhost:8080/servlet/ok2
*/
@WebServlet(urlPatterns = {"/ok1", "/ok2"})
public class OkServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("annotation doGet method");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("annotation doPost method");
}
}
@WebServlet注解源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented => 在javadoc工具生成记录
public @interface WebServlet {
String name() default "";
String[] value() default {};
String[] urlPatterns() default {};
int loadOnStartup() default -1;
WebInitParam[] initParams() default {};
boolean asyncSupported() default false;
String smallIcon() default "";
String largeIcon() default "";
String description() default "";
String displayName() default "";
}
注解详解
说明: 注解是对包进行扫描, 如果发现某个类是用@WebServlet, 就说明该类是Servlet, 然后读取urlPatterns, 看看请求的资源和urlPatterns的参数是否一致
●模拟代码
/**
* @author 赵志伟
* @version 1.0
* 模拟Tomcat是如何通过注解@WebServlet(urlPatterns={"/ok1", "/ok2"})来装载一个Servlet的
*/
@SuppressWarnings({"all"})
public class TestAnnotationServlet {
private static final HashMap<String, HttpServlet> hm = new HashMap<>();
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//1.首先要得到扫描的包 路径 IO, 进而得到类的全路径
String path = "com.zzw.servlet.annotation.OkServlet";
//2.得到OkServlet的Class对象
Class<?> aClass = Class.forName(path);
//3.根据class对象得到对应的注解
WebServlet annotation = aClass.getAnnotation(WebServlet.class);
String[] urlPatterns = annotation.urlPatterns();
for (String urlPattern : urlPatterns) {
System.out.println("urlPattern=" + urlPattern);
}
//如果匹配url, 如果是第一次, tomcat就会创建一个OkServlet实例, 放入到HashMap中
Object instance = aClass.newInstance();
System.out.println("instance=" + instance);//OkServlet实例
hm.put("OkServlet", (HttpServlet) instance);
System.out.println(hm);
}
}
initParams
@WebServlet(urlPatterns = {"/ok1", "/ok2"}, initParams = {@WebInitParam(name = "zzw", value = "123"), @WebInitParam(name = "xx", value = "yy")})
public class OkServlet extends HttpServlet {}
等同于
<servlet>
<servlet-name>OkServlet</servlet-name>
<servlet-class>com.zzw.servlet.OkServlet</servlet-class>
<init-param>
<param-name>zzw</param-name>
<param-value>123</param-value>
</init-param>
<init-param>
<param-name>xx</param-name>
<param-value>yy</param-value>
</init-param>
</servlet>
Servlet urlPattern 配置
精准匹配
@WebServlet(urlPatterns = {"/ok1/aa/bb", "/ok2"}
目录匹配
@WebServlet(urlPatterns = {"/ok1/*", "/ok2"})
http://localhost:8888/servlet/ok1
http://localhost:8888/servlet/ok1/aa
http://localhost:8888/servlet/ok1/aa/bb/cc
扩展名匹配
@WebServlet(urlPatterns = {"*.action", "/ok2"}
http://localhost:8888/servlet/zzw.action
http://localhost:8888/servlet/zzw.521.action
3.2不能带斜杠
@WebServlet(urlPatterns = {"/*.action", "/ok2"},这样是错误的
任意匹配
@WebServlet(urlPatterns = {"/", "/ok2"}
或者
@WebServlet(urlPatterns = {"/*", "/ok2"}
http://localhost:8888/servlet/aa/bb/cc
http://localhost:8888/servlet/zzw.521.action
注解注意事项
shortcuts: ctrl+alt+⬅ 回到上次访问的窗口
1.当Servlet配置了"/", 会覆盖掉tomcat的DefaultServlet, 当其它的的url-pattern都匹配不上时, 就会走这个默认的Servlet, 这样可以拦截到其它请求中的静态资源
这个默认的Servlet是处理静态资源的, 一旦拦截, 静态资源则不能处理
<!-- The default servlet for all web applications, that serves static -->
<!-- resources. It processes all requests that are not mapped to other -->
<!-- servlets with servlet mappings (defined either here or in your own -->
<!-- web.xml file). -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
2.当Servlet配置了"/*", 表示可以匹配任意访问路径
3.建议不要使用/ 和 /*, 尽量使用精准匹配
4.优先级遵守: 精确路径 > 目录路径 > 扩展名路径 > /* > / > DefaultServlet(访问静态资源)
访问:http://localhost:8888/servlet/ok1/aa
@WebServlet(urlPatterns = {"/ok1/aa"}//优先
@WebServlet(urlPatterns = {"/ok1/*"}