- Java 官方提供了 Servlet 标准,Java 官方写好一套接口就和抽象类,用于连接 Tomcat 开发者 和 应用开发者的桥梁。Servlet 是一种实现动态页面的技术,是一组 Tomcat 提供的 API, 帮助我们简单高效的开发一个 web app。
1、 servlet 开发流程
1.1 开发阶段
- servlet path
- 设置pom.xml 文件
<!--设置打包方式为 war 方式 -->
<packaging>war</packaging>
<!-- 设置 maven 的编译器版本是 1.8 -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- 添加 servlet 依赖 scope = provided表示这个依赖下的所有类只在开发、构建需要,运行时 Tomcat 内部已经有这套类了 -->
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
查找标准的依赖写法:https://search.maven.org/artifact/javax.servlet/javax.servlet-api/3.1.0/jar
- 新建存在静态资源的目录
- 设置Web应用配置
web.xml
<?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_3_1.xsd"
version="3.1">
</web-app>
- 新建java文件,动态资源
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/*
1. 继承 HttpServlet 抽象类
2. 通过 @WebServlet 注解,修饰类,填写资源路径,必须以 / 开头
3. 重写 doGet(...) 方法
*/
@WebServlet("/first")
public class FirstServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*
1. 设置响应头 Content-Type:
*/
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
/*
2. 准备响应的正文部分
*/
String s = "你好中国";
/*
3. 拿到写入正文的 writer
*/
PrintWriter writer = resp.getWriter();
/*
4. 写入正文
*/
writer.println(s);
}
}
1.2 构建阶段
-
context path
-
编译(build)----》打包(Package)----》部署(deploy)
-
也可以使用 build artifact
-
使用专业版 IDEA 自带 Tomcat 插件启动
1.3 运行阶段
- 运行 Tomcat,动态资源被修改以后,必须要重新启动 Tomcat,才可以生效。
- 在浏览器中访问资源。URL = context path + servlet path 。
1.4 常见错误
1.4.1 Tomcat 没有启动
- 之前有写过 Tomcat 无法启动的解决方案:https://blog.csdn.net/ccyzq/article/details/122182173
1.4.2 资源 URL 错误
- HTTP:404
- URL = context path(web 应用) + servlet path(各个资源)。如果在浏览器中没有输入正确的 URL ,就会出现 404 。
1.4.3 服务器内部出现问题
- 例如 动态资源中的代码出现异常,就会出现 HTTP:500 错误。
1.4.4 排查错误思路
- 小明写了一个 Web 应用,启动 Tomcat 后,访问了一个 URL 是 /hello.do 的资源,出现以下现象时,小明的怀疑是否合理?
- 1、浏览器出现 404 ,小明怀疑自己的 Tomcat 启动失败了。
不合理,浏览器出现 404 ,就说明有一个 web 服务器告诉浏览器资源是不存在的,所以,web 服务器一定是启动成功的。
但是在某些场景下是合理的,例如之前安装过类似 Tomcat 这样的 Web 服务器,这次 Tomcat 启动失败,看到的 404 是之前安装的 web 服务器所导致的。
总结:看到了HTTP 响应(1xx、2xx、3xx、4xx、5xx),都表示 web 服务器应答浏览器。没有启动只会显示无法访问,不能看到状态码。 - 2、看到资源出现404,小明怀疑自己的资源路径放置错误。
有合理性,但是还有可能是自己的 URL 输入错误。 - 3、看到资源出现500时,小明怀疑自己的资源路径放置错了/ URL输入错误。
不合理,出现500,直接看页面上的提示信息就可以。 - 4、通过开发者工具看到响应是200,但是浏览器上没有显示。
HTTP 响应 = 控制数据 (响应行 + 响应头) + 负荷数据(响应体)。说明该资源的响应行和响应头是正确的,响应体(正文)可能是空,或者其他原因导致空白的内容(html 中 < body> 下为空… ) - 5、出现405状态码。
- Method Not Allowed:客户端的问题。使用了错误的 HTTP 访问某个资源,就是 URL 对应的资源存在,但是访问的方法不对。
- 不重写 doGet 方法,通过 GET 方法访问时,实际上会执行 对象doGet 方法(METHOD_NOT_ALLOWED),就会出现 405 。
- 想要通过 post 方法访问某个资源:1、通过 form 表单,指定 method 属性。2、通过 js 代码来实现。
<form method="post" action="method">
<button>通过 post 访问</button>
</form>
1.4.5 Tomcat 打印日志信息
- 可以自己添加打印等工作。
public class method extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("运行到这里");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
resp.getWriter().println("我是处理 method 的 POST 方法的");
}
}
1.4.6 浏览器开发者工具
- 元素面板(HTML、CSS)
- 网络面板(HTTP协议)
- 前端调试面板(JS)
- 控制台面板(JS)
1.4.7 IDEA 调试器
- 主要调试后端
2、Servlet 运行基本原理
- 当浏览器给服务器发送请求的时候, Tomcat 作为 HTTP 服务器, 就可以接收到这个请求。
- Tomcat = HTTP 服务器(对接浏览器)+ Servlet 容器(对接 Web 应用)。
- HTTP 协议作为一个应用层协议, 需要底层协议栈来支持工作。
- Tomcat的工作:
- 1、通过网络读取 HTTP 请求,并解析。
- 2、判断是 静态/动态 资源。
- 3、动态资源找到对应的 Servlet 对象去处理,静态资源找路径对应下的文件,如果找不到就是404。
- 4、根据动态资源的不同方法,来调用 doGet/doPost 。
- 5、根据请求内容来填充响应对象。※
- 6、根据响应对象来组装 HTTP 相应数据。
- 7、通过网络把响应发送给浏览器。
3、Servlet 的使用
3.1 读取 HTTP 请求内容
- 请求方法、资源路径、请求头
3.2 发送响应
- ① 设置状态码,不修改的情况下就是200。
resp.setStatus(200)
。 - ② 这是响应头,
resp.setCharacterEncoding("utf-8");resp.setContentType("text/plain");
text/html、text/css、application/javascript、application/json。 - ③ 发送正文,
resp.getWriter().println();
3.3 获取浏览器(用户)提交的数据
- ① GET 方法获取(参数来自 URL 的 querystring 部分,?key1=value1&key2=value2)
package com.cc.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/get-param")
public class GetParam extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String age = req.getParameter("age");
System.out.printf("name = %s, age = %s\n",name, age);
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/plain");
PrintWriter writer = resp.getWriter();
writer.printf("name = %s, age = %s\n&#