哈喽,小友们,Javaweb课程学习第二站,servlet的相关知识概念,感兴趣的宝子一起来学哦。
点赞收藏加关注,下次学习不迷路(❁´◡`❁)
Javaweb
2、Servlet的开发步骤
Servlet是一种Java编写的服务器端程序,用于生成动态Web内容。它运行在支持Java的应用服务器上,通过处理客户端请求和生成响应来交互式地浏览和修改数据。
1,在pom.xml文件中加入如下配置,设置项目编译采用的JDK版本和字符编码
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
2,引入Servlet依赖
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
3,创建类,实现Servlet接口,实现接口中的方法
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//Servlet实例化后,Servlet容器调用该方法完成初始化工作
}
@Override
public ServletConfig getServletConfig() {
return null;
//用于获取Servlet对象的配置信息,返回Servlet的ServletConfig对象
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {//负责响应用户的请求,当容器接收到客户端访问Servlet对象的请求时就会调用此方法。
}
@Override
public String getServletInfo() {
return null;
//返回一个字符串,其中包含关于Servlet的信息,例如,作者、版本和版权等信息
}
@Override
public void destroy() {
//负责释放Servlet对象占用的资源
}
}
4,在service方法中处理请求和响应数据
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
// TODO: 处理请求的逻辑
// 向浏览器响应内容 Hello Servlet
// 1.获取向浏览器写出内容的输出流
PrintWriter writer = servletResponse.getWriter();
// 2.写出内容
writer.println("Hello Servlet");
}
5,在web.xml文件中配置Servlet访问地址
<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">
<!-- Servlet信息配置-->
<servlet>
<!--Servlet的名称-->
<servlet-name>helloServlet</servlet-name>
<!-- Servlet类的全限定名 -->
<servlet-class>cn.jj.HelloServlet</servlet-class>//根据你的文件所在目录导入
</servlet>
<!-- Servlet访问地址配置 -->
<servlet-mapping>
<!--Servlet名称:与上面配置的名称一致-->
<servlet-name>helloServlet</servlet-name>
<!-- 浏览器访问地址,必须以/开头 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
6,部署项目,并通过浏览器访问Servlet
2.1、注解方式配置Servlet
@WebServlet 注解
注解开发Servlet
1.编写Servlet,通过注解@WebServlet配置访问地址
@WebServlet(name = “hello2”,urlPatterns = {“/hello3”,“/hello3”})与下列web.xml文件含义相同
@WebServlet(name = "hello2",urlPatterns = {"/hello3","/hello3"})
public class HelloServlet2 implements Servlet {
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
res.getWriter().println("Hello Servlet2");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
通过浏览器访问Servlet
2.2,Servlet生命周期
生命周期: 从出生到死亡以及中间所经历的过程则称为一个生命周期
对象的生命周期: 创建对象–> 运行操作–>销毁操作
Servlet 对象的生命周期:Servlet 创建对象–>初始化操作–> 运行操作–>销毁操作
Web 服务器管理了 Servlet 的生命周期,Servlet 对象整个过程都是 Web 服务器来管理的。
servlet 接口中生命周期方法
生命周期方法 | 作用 | 运行次数 |
---|---|---|
构造方法 | 在对象实例化的时候执行 必须有公共的无参数构造方法 | 1次 |
void init(ServletConfig config) | 在初始化的时候执行 | 1次 |
void service(ServletRequest req, ServletResponse res) | 每次请求都会执行 | n次 |
void destroy() | 在服务器正常关闭的时候 | 1次 |
- 生命周期方法执行顺序图
@WebServlet("/hello3")
public class HelloServlet3 implements Servlet {
public HelloServlet3() {
System.out.println("构造方法被调用");
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init方法被调用");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("处理浏览器发送请求");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destory方法被调用");
}
}
启动服务器,浏览器输入http://localhost:8080/hello3
访问HelloServlet3,出现以下效果
刷新浏览器,多次访问HelloServlet3,控制台打印结果如下:
关闭服务器时,Servlet容器会调用HelloServlet3的destroy()方法,在IDEA控制台打印出“destroy 方法被调用”
2.3,loadOnStartup 属性
1,作用
让 Servlet容器启动的时候创建并初始化 Servlet。
2,用法:
数字小的优先执行
-
web.xml配置用法
注解配置用法
2.4,Servlet 的继承体系
1,GenericServlet类
GenericServlet默认实现了 Servlet 和 ServletConfig 这两个接口,它的子类是 HttpServlet,如果我们写的Servlet
使用的是 Http 协议,建议继承于 HttpServlet。
2, HttpServlet类
@WebServlet("/hello5")
public class HelloServlet5 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Hello HttpServlet");
}
}
2.5,ServletAPI
HttpServletRequest 对象
HttpServletRequest 是一个接口,该接口的实现类对象称为请求对象,请求对象封装了所有的请求信息(请求行,请求头,请求体(请求参数))。
HttpServletRequest 接口包含了大量的方法。由 Tomcat 去实现这个对象,并且在 servlet 启动的时候调用service() 将请求对象传递进来了。我们在 service 方法中直接使用即可。
request获取请求行相关方法 | 功能描述 |
---|---|
String getMethod() | 该方法用于获取请求行中的请求方式(如GET、POST等) |
String getRequestURI() | 该方法用于获取请求行中资源名称部分Uniform Resource Identifier统一资源标识符,代表一个资源名字 |
StringBuffer getRequestURL() | 该方法用于获取客户端发出请求时的完整URL,包括协议、服务器名、端口号、资源路径等信息,<br但不包括后面的查询参数部分。 Uniform Resource Locator 统一资源定位符,代表一个可以访问地址 |
String getProtocol() | 该方法用于获取请求行中的协议名和版本 |
String getContextPath() | 该方法用于获取请求URL中属于Web应用程序的路径,这个路径以“/”开头,表示相对于整个Web站点的根目录,路径结尾不含“/”。 如果请求URL属于Web站点的根目录,那么返回结果为空字符串(“”) |
String getScheme() | 该方法用于获取请求的协议名 |
package cn.jj;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/requestLine")
public class RequestLineServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("请求方式:" + req.getMethod());
System.out.println("请求资源名称:" + req.getRequestURI());
System.out.println("请求资源URL:" + req.getRequestURL());
System.out.println("请求协议和版本:" + req.getProtocol());
System.out.println("请求Web应用程序名称:" + req.getContextPath());
System.out.println("请求协议名:" + req.getScheme());
}
}
request获取请求头相关方法 | 功能描述 |
---|---|
String getHeader(String headName) | 得到指定的请求头的值 参数:键的名字 返回:相应请求头的值 |
Enumeration getHeaderNames() | 该方法用于获取一个包含所有请求头字段的Enumeration对象 |
request与请求参数相关方法 | 功能描述 |
---|---|
String getParameter(String name) | 该方法用于获取某个指定名称的参数值 如果请求消息中没有包含指定名称的参数,getParameter()方法返回null; 如果指定名称的参数存在但没有设置值,则返回一个空串; 如果请求消息中包含有多个该指定名称的参数 getParameter()方法返回第一个出现的参数值 |
String[] getParameterValues(String name) | 根据参数名得到一组同名的值 复选框,下拉列表多选 |
Enumeration getParameterNames() | 获得所有的参数名 |
Map getParameterMap() | 获取所有的参数键和值,封装成Map对象 |
请求对象获取请求参数
页面文件放在webapp文件夹中
method提交方式,action表单提交位置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<h2>用户注册</h2>
<form action="/register" method="post">
用户名: <input type="text" name="name"><br/>
密 码: <input type="password" name="password"><br/>
性别: <input type="radio" name="gender" value="男" checked="checked"/>男
<input type="radio" name="gender" value="女"/>女 <br/>
<select name="city">
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
</select>
爱好:
<input type="checkbox" name="hobby" value="java"/>java
<input type="checkbox" name="hobby" value="python"/>python
<input type="checkbox" name="hobby" value="C++"/>C++
<input type="checkbox" name="hobby" value="rap"/>rap<br>
<!-- 隐藏域:<input type="hidden" name="token" value="{{token}}"/>-->
<br/>
<input type="submit" value="注册"/>
<input type="reset" value="重置"/>
</form>
</body>
</html>
package cn.jj;
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;
@WebServlet("/register")
public class RegisterServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");//解决请求参数乱码问题
// 根据参数名获取参数值
String name = req.getParameter("name");
String gender = req.getParameter("gender");
String city = req.getParameter("city");
System.out.println("用户名:" + name);
System.out.println("性别:" + gender);
System.out.println("城市:" + city);
// 获取参数名为 hobby 的值,由于hobby参数值是复选框,可能会存在多个,故使用 getParameterValues获取
String[] hobbies = req.getParameterValues("hobby");
System.out.print("爱好:");
for (String hobby : hobbies) {
System.out.print(hobby + ",");
}
}
}
注册用户出现404解决方法
请求参数乱码问题
在浏览器发送数据给服务器的时候,使用 utf-8 编码,但服务器解码默认使用 ISO-8859-1 解码:欧洲码,不支持汉字。编码不匹配。
解决请求参数中文乱码
-
解决方法: 设置请求参数的编码为UTF-8
-
代码位置:设置请求编码这条语句一定放在获取请求参数之前
req.setCharacterEncoding("UTF-8");
2.6,响应对象
HttpServletResponse 是一个接口,该接口的实现类对象称为响应对象,用于响应数据(响应行,响
应头,响应体)给浏览器。HttpServletResponse 接口包含了大量的方法。由 Tomcat 去实现这个对象,
并且在 servlet 启动的时候调用 service() 将请求对象和响应对象传递进来。我们在 service 方法中直
接使用即可。即服务器收到请求命令,做出的回应,通过浏览器展示。
响应信息给浏览器
响应信息相关方法
设置响应头相关方法 | 功能描述 |
---|---|
void addHeader(String name, String value) | 该方法用来设置响应头字段,其中 参数name用于指定响应头字段的名称, 参数value用于指定响应头字段的值。 该方法可以增加同名的响应头字段 |
void setHeader(String name, String value) | 功能同上,不同的是,该方法会覆盖同名的响应头字段 |
void setContentType(String type) | 该方法用于设置输出内容的MIME类型, 对于HTTP协议来说,就是设置Content-Type响应头字段的值。 如:如果发送到客户端的内容是jpeg格式的图像数据,就需要将响应头字段的类型设置为“image/jpeg”。 需要注意的是,如果响应的内容为文本,setContentType()方法的还可以设置字符编码,如:text/html;charset=UTF-8 |
void setCharacterEncoding(String charset) | 该方法用于设置输出内容使用的字符编码,对HTTP 协议来说,就是设置Content-Type头字段中的字符集编码部分。如果没有设置Content-Type头字段,setCharacterEncoding方法设置的字符集编码不会出现在HTTP消息的响应头中 |
设置响应体相关方法 | 功能描述 |
---|---|
ServletOutputStream getOutputStream() | 如果服务器端返回的是二进制数据则使用这个方法,比如图片 |
PrintWriter getWriter() | 如果服务器端返回的是字符的文本数据,使用这个方法 |
resp.setContentType("text/html; charset=utf-8");
2.7,Web组件跳转
Servlet之间可以相互跳转,利用Servlet的跳转可以很容易地把一项任务按模块分开,例如,使用一个Servlet实现用户登录,然后跳转到另外一个Servlet响应结果给浏览器。
请求转发and页面跳转
request对象与转发相关方法 | request.getRequestDispatcher(“/要跳转的地址”).forward(request,response); |
---|
简单的登录系统(登录页面,请求----->响应)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="login" method="post">
账号:<input type="text" name="name"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
package cn.jj;
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;
@WebServlet("/login")
public class Login extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");//解决请求乱码
String name = req.getParameter("name");
String password = req.getParameter("password");
req.setAttribute("name",name);
req.getRequestDispatcher("/result").forward(req,resp);//将网页数据从页面跳转到响应页面
}
}
package cn.jj;
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;
@WebServlet("/result")
public class result extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");//解决响应中乱码
String name=(String)req.getAttribute("name");//获取请求页面中的数据
resp.getWriter().print("欢迎:"+name+"登录本系统");
}
}
作为域对象使用
作用域对象
用于 Servlet 之间数据共享的服务器内存区域,作用域结构是一个Map<String, Object>。
作用域对象方法
与作用域有关的方法 | 作用 |
---|---|
void setAttribute(String key, Object value) | 向作用域中存储键值对数据 |
Object getAttribute(String key) | 从作用域中根据key获取对应value |
void removeAttribute(String name) | 删除作用域中的键值对数据 |
重定向方法
response对象与重定向相关方法 | response.sendRedirect(“要跳转的地址”) |
---|
请求转发和重定向的区别
练习:简单的登陆页面
要求:登陆一个账号:马小信,密码:123456 登录成功显示欢迎+name+登录本系统,失败显示 账号或密码错误
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="login" method="post">
账号:<input type="text" name="name"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
package cn.jj;
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;
@WebServlet("/login")
public class Login extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String name = req.getParameter("name");
String password = req.getParameter("password");
req.setAttribute("name",name);
req.setAttribute("password",password);
String uname="马***";
String upassword="123456";
boolean flag;
if (name.equals(uname)&&password.equals(upassword)) {//判断密码是否相等时,不能直接用==,需要用equals
flag=true;
}else {
flag=false;
}
req.setAttribute("flag",flag);
req.getRequestDispatcher("/result").forward(req,resp);
}
}
package cn.jj;
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;
@WebServlet("/result")
public class result extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
String name=(String)req.getAttribute("name");
boolean flag=(boolean)req.getAttribute("flag");
if(flag){
resp.getWriter().print("欢迎,"+name+"少爷,登录本系统");
}else{
resp.getWriter().print("账号或密码错误");
}
}
}
输入你给定的账号密码
简单的注册页面
显示账号密码,并在注册成功页面展示账号密码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户注册</h1><br>
<form action="/registerServlet" method="get">
账号:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
<input type="submit" value="注册">
</form>
</body>
</html>
package cn.jj;
public class User {
private String username;
private String password;
User(){
}
User(String username,String password){
this.username =username;
this.password=password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package cn.jj;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
protected void service( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取表单数据
String username = request.getParameter("username");
String password = request.getParameter("password");
// 将数据封装到User对象中
User user = new User(username, password);
// 将User对象添加到请求属性中
request.setAttribute("user", user);
// 请求转发到ResultServlet
request.getRequestDispatcher("/resultServlet").forward(request, response);
}
}
package cn.jj;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/resultServlet")
public class ResultServlet extends HttpServlet {
protected void doGet( HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 从请求属性中获取User对象
response.setContentType("text/html;charset=UTF-8");
User user = (User) request.getAttribute("user");
// 设置响应内容类型
// 输出结果
response.getWriter().println("<h2>恭喜你注册成功</h2>");
response.getWriter().println("<br>");
response.getWriter().println("<p>账号: " + user.getUsername()+"</p>");
response.getWriter().println("<br>");
response.getWriter().println("<p>密码: " + user.getPassword() + "</p>");
response.getWriter().println("<br>");
response.getWriter().println("<p>请牢记账号密码!!!</p>");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.jj</groupId>
<artifactId>zhangjunjie</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>23</maven.compiler.source>
<maven.compiler.target>23</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!--设置项目的属性信息-->
<!--设置项目的属性信息-->
<!-- <properties>-->
<!-- <maven.compiler.source>11</maven.compiler.source>-->
<!-- <maven.compiler.target>11</maven.compiler.target>-->
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
<!-- </properties>-->
<!--依赖信息-->
<dependencies>
<!--Servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
<?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-app>