1 Servlet简介:
1.1 什么是Servlet
Servlet是一种用Java编写的Web应用程序组件,其主要作用是接收和处理来自Web浏览器发送的HTTP请求,并返回相应的HTTP响应。Servlet运行在Java Servlet容器中,可以动态生成HTML页面、接受表单数据、处理业务逻辑等。Servlet可以与JSP结合使用,将Java代码和页面布局分离,提高了Web应用程序的可维护性和可扩展性。Servlet技术是Java企业级Web开发中的重要组件,广泛应用于各种Web应用程序中。
Servlet规范:包含三个技术点
- servlet技术
- firter技术---过滤器
- listener技术---监听器
1.2 Servlet快速入门
1.2.1
Servlet 是一种基于 Java 语言的 Web 应用程序组件,它可以接受来自客户端的请求并作出响应。下面是 Servlet 实现的基本步骤:
-
编写 Servlet 类:通过继承 HttpServlet 类或 GenericServlet 类来创建一个 Servlet 类。
-
重写 Servlet 的 doGet()、doPost()、doPut()、doDelete() 等方法:在这些方法中编写业务逻辑,并将响应内容输出到客户端。
-
配置 Servlet:在 web.xml 配置文件中添加 Servlet 的配置信息,包括 Servlet 名称、Servlet 类名、URL 映射等。
-
部署 Servlet:将 Servlet 类文件打包成 WAR 文件,并将 WAR 文件放置在 Web 服务器的 WEB-INF 目录下。
-
启动 Web 服务器:启动 Web 服务器,访问 Servlet 对应的 URL 地址,即可执行 Servlet。
-
调试 Servlet:通过 Web 服务器的日志输出信息和浏览器的 Network Tab 来调试 Servlet。
注意事项:
-
Servlet 编写的代码应该具有线程安全性。
-
Servlet 需要在 Web 服务器中运行,比如 Tomcat、Jetty、WebLogic 等。
-
Servlet 不能访问本地文件系统,而只能通过网络访问资源。
-
Servlet 不能直接映射页面,而只能在响应中输出 HTML、JSON、XML 等格式的数据。
但是在实际开发中,我们不会直接去实现Servlet接口,因为其覆盖的方法太多,我们一般创建类继承HttpServlet,实现步骤:
方法一:通过类实现Servlet接口来使用(了解):
自定义实现Servlet接口:
public class Demo1Servlet implements Servlet {
// servlet初始化时调用, 对象通常在创建后初始化
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("Demo1Servlet init");
}
// 服务方法
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Demo1Servlet 接收到了请求");
PrintWriter writer = servletResponse.getWriter();
writer.println("<h1>Demo1Servlet " + new Date() + "</h1>");
writer.flush();
}
// 销毁方法: 是在对象销毁前调用
public void destroy() {
System.out.println("Demo1Servlet destroy");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
}
2.注册servlet -> web.xml
<servlet>
<servlet-name>demo1</servlet-name>
<servlet-class>全限定类名</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
我们不会直接去实现Servlet接口,因为其覆盖的方法太多,我们一般创建类继承HttpServlet来实现:
public class Demo2Servlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get请求 Demo2Servlet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
Systrm.out.println("post请求")
}
}
1.2.2 画图描述整个访问过程:
2 Servlet的API(生命周期):
2.1Servlet接口中的方法
2.1.1init(ServletConfig config)
何时执行:servlet对象创建的时候执行
ServletConfig:代表的是该servlet对象的配置信息
2.1.2 service(ServletRequest request, ServletResponse response)
何时执行:每次请求都会执行
ServletRequest:代表请求,ServletRequest内部封装的是http请求的信息
ServletResponse: 代表响应,要封装的是响应的信息
2.1.3 Destroy()
何时执行:servlet销毁的时候执行
2.2 HttpServlet类的方法
- init()
- doGet(HttpServletRequest request, HttpServletResponse response)
- doPost(HttpServletRequest request, HttpServletResponse response)
- destroy()
2.3 Servlet的生命周期(重要)
init: 对象初始化时调用 对象是在创建后初始化 对象什么时候创建: 默认第一次访问资源时 可以通过标签 <load-on-startup>int 来修改为服务器启动时创建 destroy: 对象销毁前调用 对象什么时候销毁: 服务器关闭之前销毁 service: servlet接收到请求时调用 结论: 在整个服务器(应用)运行期间, Servlet 是单例的 提问: 对xxxServlet进行10次访问, init(), destory(), service(), doGet(), doPost() 分别执行了多少次,request对象创建了多少个, response创建了多少个?
答:1次,0次(结束:1次),10次,不确定,不确定,10个,10个
- doGet()方法:doGet()方法是用于处理HTTP GET请求的方法。根据描述,无法确定具体调用了多少次doGet()方法,因为在service()方法内部会根据请求类型来决定调用doGet()还是doPost()方法。
- doPost()方法:doPost()方法是用于处理HTTP POST请求的方法。同样地,我们无法确定具体调用了多少次doPost()方法,需要根据请求类型来确定
提问:每次访问必然执行的方法
service(ServletRequest req, ServletResponse res)方法
注意: 服务器启动? 服务器关闭? 应用的安装和启动 应用的卸载和关闭 Servlet -> HttpServlet extends GenericServlet implements Servlet 1. HttpServlet 间接实现了 Servlet 接口 2. 实现了Servlet接口中的service方法 将请求和响应做了类型转换后, 调用了 this.service 方法 3. this.service 方法中 如果请求方式是get: 调用doGet方法 如果请求方式是Post: 调用doPost方法 4. 重写 doGet 或者 doPost
3 Servlet的配置:
3.1基本配置
1.url-partten:Servlet访问路径,一个Servlet可以定义多个访问路径。
2.url-pattern写法三种: <!-- 1.完全匹配的写法, 怎么写的怎么访问 --> <url-pattern>/user/demo2</url-pattern> -> 优先级最高 <!-- 2.目录匹配的写法, 有(没有)目录作为统一前缀, 后面使用通配符 * --> <url-pattern>/user/*</url-pattern> -> 优先级第二 <!-- 3.后缀匹配的写法, 有统一后缀, 前面使用通配符 * 注意: 后缀匹配, 前面不能用目录, 不能用 / --> <url-pattern>*.do</url-pattern> -> 优先级第三, 甚至高于静态资源 不推荐后缀是常见文件后缀 .user .admin .do .action <!-- 4.默认(缺省)的配置, / 不建议修改, 了解什么是DefaultServlet --> <url-pattern>/</url-pattern> -> 最四优先级, 高于静态资源 默认的配置: 当在web.xml里面找不到任何映射的资源时, 就会去访问default配置 / 静态资源, 不是直接找文件, 也是在web应用中找路径对应的Servlet映射 在发送请求时, tomcat 解析url路径(访问的是哪个应用), 后面的路径是访问的资源 路径搜索有没有对应的映射, 自己应用中的描述文件web.xml, tomcat的描述文件web.xml tomcat的web.xml文件中定义了默认的DefaultServlet, 可以处理所有的静态资源 3.web3.5版本以上, 就支持注解配置 @WebServlet(name="Demo4Servlet", urlPatterns = {"/demo4", "/hi/demo4"}, loadOnStartup = 2)
HttpServletRequest: 请求 HttpServletResponse: 响应 ServletConfig对象: Servlet配置对象 init: Servlet对象初始化时, tomcat负责传递进来的 配参数: web.xml文件中 <servlet> <init-param> <param-name>driver</param-name> <param-value>com.mysql.cj.jdbc.Driver</param-value> </init-param> </servlet>
@WebServlet(value="/config",
initParams = {@WebInitParam(name="user", value = "root"),
@WebInitParam(name="driver", value = "com.mysql.jdbc.Driver")})
public class DemoConfigServlet extends HttpServlet {
/*@Override
public void init(ServletConfig config) throws ServletException {
}*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletConfig config = this.getServletConfig();
// 获得servlet的初始化参数(注册servlet的时候配置的)
String user = config.getInitParameter("user");
response.getWriter().println("user: " + user);
// 获得所有参数的名字
Enumeration<String> names = config.getInitParameterNames();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
ServletContext: 应用上下文, 一个应用中只有一个的 基础方法:getRealPath() 获得资源的绝对路径 getContextPath() 获得应用名 getInitParam() 获得servlet中的初始化参数(value值) web.xml 配置 :<context-param> 生命周期: 应用运行期间只有一个 创建: 开启服务器创建 销毁: 关闭服务器销毁
域的范围:服务器运行期间,数据是临时的,不是持久的
1.获得ServletContext对象:
![](https://i-blog.csdnimg.cn/blog_migrate/1405f8d7641350b9a6f4c27a658d6d4e.png)
@WebServlet("/context")
public class DemoContextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获得ServletContext
// 方式1: 通过ServletConfig获得
// 方式2: 通过request获得
ServletContext context = request.getServletContext();
// 方式3: 通过Servlet获得
ServletContext application = this.getServletContext();
System.out.println(application == context);
//将ServletContext域中的msg参数移除
servletContext.removeAttribute("msg");
// 所有的基础功能都和get相关
// 功能1: 可以动态获得应用名 - 应用名因为可能随时变, 所以不要写在代码中
String path = application.getContextPath();
response.getWriter().println("path: " + path);
// 功能2: 可以获得应用的初始化参数 -> 只能写在web.xml
String password = application.getInitParameter("password");
response.getWriter().println("password: " + password);
// 功能3: ☆☆☆☆☆获得应用中资源的绝对路径
// a.txt -> web工程/src/a.txt
// b.txt -> web工程/web/b.txt
// c.txt -> web工程/web/WEB-INF/c.txt
// d.txt -> web工程/d.txt -> 不会出现在应用中
String aPath = application.getRealPath("WEB-INF/classes/a.txt");
String bPath = application.getRealPath("b.txt");
String cPath = application.getRealPath("WEB-INF/c.txt");
response.getWriter().println("a: " + aPath);
response.getWriter().println("b: " + bPath);
response.getWriter().println("c: " + cPath);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
3.2 服务器启动实例化Servlet配置:
Servlet何时创建:默认第一次访问时创建
为什么是默认?
当在servlet配置时,加上一个配置<load-on-startup>servlet对象在服务器启动时就创建。