环境
在IDEA中创建JavaEE项目
项目运行后,会显示webapp中的index.html
或index.jsp
中的内容,
调试
- 用Lombok里的
@Log
,或者System.out.println()
0、JavaEE项目运行
两种方法:
- 直接运行项目
- 将项目打包,生成一个war包,之后在Tomcat中运行
下面是第二种方法:
运行startup.bat
,启动Tomcat
Tomcat中有默认的servlet-mapping,所以我们才能看到Tomcat 的页面
1、创建Servlet
Servlet是一个标准,web服务器Tomcat支持此标准。官方定义接口,程序员实现,之后Web服务器(Tomcat)运行这些实现。
用注解注册一个Servlet
java
@WebServlet("/test")
public class TestServlet implements Servlet {
public TestServlet(){
System.out.println("我是构造方法!");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init");
}
@Override
public ServletConfig getServletConfig() {
System.out.println("我是getServletConfig");
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("我是service");
}
@Override
public String getServletInfo() {
System.out.println("我是getServletInfo");
return null;
}
@Override
public void destroy() {
System.out.println("我是destroy");
}
}
在web.xml
中注册Servlet【一般不用】
xml
<!-- Servlet,对应的是哪个文件-->
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.example.webtest.TestServlet</servlet-class>
</servlet>
<!-- 映射(通过哪个路径访问)-->
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
2、Servlet的生命周期
问题:Servlet启动/关闭时,哪些方法被执行了?
答:
请求url时,初始化Servlet(构造方法,init)
调用Service处理客户端请求
//中间的多次请求,只调用Service
销毁前调用destroy方法
最后用JVM的垃圾回收器,进行回收
3、Servlet的Service方法
java
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("我是service");
}
参数:
servletRequest
:客户端发送的HTTP请求,被接收到这里(可从这获取所有请求信息)servletResponse
:返回给客户端的HTTP响应报文
c
System.out.println("浏览器发起了一次请求");
System.out.println(servletRequest.getClass().getName());//记录请求对象的类名。
System.out.println(servletResponse.getClass().getName()); //记录响应对象的类名。
3.1 使用HttpServletRequest,处理HTTP请求
在后端查看请求信息
java
/*写在service方法中*/
System.out.println("我是service");
// 将通用的ServletRequest对象转换为更具体的HttpServletRequest对象,以便可以访问HttpServletRequest特有的方法和属性。
HttpServletRequest request = (HttpServletRequest) servletRequest;
System.out.println("请求使用的协议: " + request.getProtocol());// 打印请求使用的协议
System.out.println("客户端的IP地址: " + request.getRemoteAddr()); // 打印客户端的IP地址
System.out.println("请求的URI: " + request.getRequestURI());// 打印请求的URI
System.out.println("打印请求的方法(如GET、POST): " + request.getMethod());// 打印请求的方法(如GET、POST)
// 获取头部信息
// 获取请求头的所有名称
Enumeration<String> enumration = request.getHeaderNames();
// 遍历所有请求头名称,并打印其对应的值
while (enumration.hasMoreElements()) {
String name = enumration.nextElement();// 获取请求头名称
String value = request.getHeader(name);// 获取当前名称对应的值
System.out.println(name + "--->" + value);// 打印请求头名称和值
}
运行结果
3.2 使用HttpServletResponse,编写响应内容
java
/*写在service方法中*/
// 将Servlet响应转换为HTTP响应对象,以便更直接地操作响应头和内容。
HttpServletResponse response=(HttpServletResponse) servletResponse;
// 设置响应头的Content-Type,指定响应内容类型为HTML,编码为UTF-8。
response.setHeader("Content-Type","text/html;charset=UTF-8");
// 将指定的HTML内容写入响应体。
response.getWriter().write("<h1>我是响应内容!</h1>");
3.3 继承HttpServlet,简化开发
核心思想:重写HttpServlet中的方法,简化JavaWeb项目的开发
类的继承关系:类HttpServlet
继承 类GenericServlet
实现 接口Servlet
GenericServlet
没有实现service
3.3.1 直接访问,会执行doGet(),显示方法不可用
3.3.2 重写doGet()方法后,会执行重写后doGet()方法
java
@WebServlet("/test")
public class TestServlet extends HttpServlet {
//重写doGet()方法
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("<h1>恭喜你解锁了全新玩法</h1>");
}
}
3.4 @WebServlet注解,怎么写
注解的作用:把这个类注册为Servlet,之后该类会按Servlet的方式运行。
注解中的参数:这个Servlet运行时的一些配置
常用tips
*
代表任意
3.4.1 指定访问的URL
此处URL是/test/任意字符
,如/test
,/test/123
,/test/456asdf
java
@WebServlet("/test/*") // URL: /test/任意字符
@WebServlet(value = "/test/*") // 另一种写法,更全
3.4.2 指定文件后缀
java
// 解释:获取以.html结尾的文件时,会调用这个Servlet
@WebServlet("*.html")
// 解释:获取以.js结尾的文件时,会调用这个Servlet
@WebServlet("*.js")
3.4.3 特殊URL
/
代表若Tomcat没有找到对应的URL,则进入这个路由(一般是404)
- 注:前缀URL必须正确,如
java
@WebServlet("/")
3.4.4 配置多个URL
java
@WebServlet({"/test1","/test2"})
3.4.5 Servelet在项目启动时是否加载(init方法)
loadOnStartup = 1
加载- 数字代表启动顺序,顺序:
1,2,3,....
- 数字代表启动顺序,顺序:
loadOnStartup = -1
不在启动时加载,在被访问时才会加载
java
//写了多个参数,要用 name=value 格式
@WebServlet(value = {"/t21","/t22"},loadOnStartup = 2)
3.4.6 其他参数
怎么看?
查看@WebServlet
的定义即可
4、用Post请求实现登录
实现一个登录页面+功能,代码见下方链接。
简易的Web登录功能(Servlet,mybatis,MySQL)
5、Servlet实现文件的上传/下载
6、前端XHR请求数据
- 页面上的部分内容,动态显示
- 如:时间旁有个按钮,点击按钮可刷新时间
7、重定向VS请求转发
7.1 重定向
- 登陆后,跳转到主页
- 关键:
resp.sendRedirect("main");
- 流程
- 前端:输入账号密码,登录,访问/login
- 后端:执行/login的doPost(),执行重定向
- 前端:收到重定向响应(状态码302),访问主页/main
- 后端:执行/main的doGet(),返回主页面的页面html
基础程序:简易的Web登录功能(Servlet,mybatis,MySQL)
修改1:登录成功
修改2:创建类MainServlet
手动设置重定向
java
//自动重定向
resp.sendRedirect("main");//执行重定向
//手动重定向
resp.setStatus(302);
resp.setHeader("Location", "main");
//重定向到百度
resp.setStatus(302);
resp.setHeader("Location", "https://www.baidu.com");
7.2 请求转发:
- 后端内部转发
req.getRequestDispatcher("/main").forward(req,resp);
- 流程
- 前端:输入账号密码,登录,访问/login
- 后端:执行/login的doPost(),执行请求转发
- 后端:执行/main的doPost(),返回主页面信息
- 前端:接收到主页面信息,显示
基础程序:简易的Web登录功能(Servlet,mybatis,MySQL)
修改1:登录成功
修改2:创建类MainServlet
对比
重定向 | 请求转发 | |
---|---|---|
前端发起请求次数 | 2 | 1 |
前端地址栏变化 | 变 | 不变 |
能否共享请求参数 | 不能 | 能 |
只能转发给项目内的Servlet |
8、ServletContext对象
ServletContext
是个全局变量,属于整个Web App,可通过getServletContext()
获取
功能1:传递数据(键值对)
存储数据:
java
// 获取Servlet上下文对象,该对象在整个Web应用程序中都是唯一的
ServletContext context = getServletContext();
// 设置一个属性"test_data",并赋值为"我是数据test_data"
// 这个属性可以在Web应用的任何地方访问,只要拥有对ServletContext的引用
// 这种方式常用于在多个Servlet之间共享数据,或者存储配置信息
context.setAttribute("test_data", "我是数据test_data");
获取数据:
java
// 获取Servlet上下文对象,该对象在整个Web应用程序中都是唯一的
ServletContext context = getServletContext();
// 从Servlet上下文中尝试获取之前设置的"test_data"属性的值
// 如果存在该属性,将打印其值;否则,将打印null
System.out.println(context.getAttribute("test_data"));
功能2:请求转发
java
// 获取Servlet上下文对象,该对象在整个Web应用程序中都是唯一的
ServletContext context = getServletContext();
// 使用Servlet上下文的Dispatcher来转发请求到"/main"路径的资源
// 这将导致请求和响应对象被传递给"/main"路径所映射的Servlet或JSP页面
// 请求转发是一个服务器端操作,客户端浏览器不会看到实际的URL改变
// "/main"应该是Web应用内部的一个有效路径,例如一个Servlet或JSP页面
context.getRequestDispatcher("/main").forward(req, resp);
9、初始化参数
在Servlet中存储初始化参数,如
- 数据库连接信息:账号,密码,url
- 系统设置:如缓存策略、日志级别、邮件服务器设置
- APIKey:如高德地图,百度AI等的APIKey
9.1 Servlet中的初始化参数
格式(键值对形式)
java
@WebServlet(value = "/login", initParams = {
@WebInitParam(name = "test", value = "我是初始化参数test")//初始化参数在这
})
通过getInitParameterNames()
方法获取初始化参数的"名称"(name)
java
// 获取初始化参数的名称枚举
Enumeration<String> paramNames = getInitParameterNames();
// 遍历并输出所有初始化参数的名称
while (paramNames.hasMoreElements()) {
//while (paramNames.hasMoreElements())检查枚举是否还有未处理的元素(即参数名)。
//如果有的话,paramNames.nextElement()会获取下一个参数名,并将其赋值给paramName。
String paramName = paramNames.nextElement();
System.out.println(paramName);
}
通过Servlet的getInitParameter()
方法获取初始化参数
java
//根据name获取value
System.out.println(getInitParameter("test"));
9.2 全局初始化参数
在web.xml
编写
xml
<context-param>
<param-name>test_quanjv</param-name>
<param-value>我是全局初始化参数</param-value>
</context-param>
用ServletContext
来读取全局初始化参数:
java
/**
* 获取Web应用程序的ServletContext对象。
* ServletContext对象代表了整个Web应用程序的上下文环境。
* 之后,从ServletContext对象中获取名为"test_quanjv"的初始化参数的值。
* 如果该参数存在,其值将被输出到控制台。
*/
ServletContext context = getServletContext();
// 输出名为"test_quanjv"的初始化参数的值
System.out.println(context.getInitParameter("test_quanjv"));