Servlet
Servlet是在Web服务器运行的Java程序,主要负责与客户端数据交互,生成动态的Web内容。通常 通过HTTP 进行 接收 和 响应 来自客户端的请求!
工作步骤:
- 服务器 启动Servlet
- 客户端 发送请求 至服务器
- 服务器 调用Servlet,根据 客户端 请求内容 传给服务器
- 服务器 响应返回 客户端
Servlet API
implements Servlet
java.lang.Object
javax.servlet
用于 接收请求 与 响应请求 ,服务器必须实现的方法
返回 | 抽象方法 | 说明 |
void | init() | 构造服务器 |
void | service() | 服器器 响应请求 |
void | destroy() | 移出 服务器 视为垃圾 |
ServletConfig | getServletConfig() | 获取 服务器对象 |
String | getServletInfo() | 获取 有关服务器的信息 |
class abstract GenericServlet
java.lang.Object
javax.servlet
GenericServlet类 实现 Servlet接口
用于Web的 HTTP Servlet 服务项
返回 | 方法 | 说明 |
Enumeration | getInitParameterNames() | 获取 指定参数名的对象 |
Enumeration | getServletName() | 获取 服务名 |
ServletContext | getServletContext() | 获取 全局对象 |
class abstract HttpServlet
java.lang.Object
javax.servlet.GenericServlet
javax.servlet.http
HttpServlet 继承 GenericServlet类
处理 请求数据
返回 | 方法 | 说明 |
void | doGet() | 处理GET请求 |
void | doPost() | 处理POST请求 |
void | doPut() | 处理PUT请求 |
··· | … | …(更多自查文档) |
implements ServletContext
用于与其他 servlet容器 通信的方法
Servlet 应用
- 在
web
创建 index.html ,模拟客户端请求发送
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>!!!</title>
</head>
<body>
<h1>No.1 Servlet应用</h1>
<a href="test">get请求测试</a>
<form action="test" method="post">
<input type="submit" value="post-test">
</form>
</body>
</html>
- 创建实现Servlet类,继承
HttpServlet类
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: 柏竹
* @Description: 一个简洁主义...
* @Date_Created_in: 2021-04-09 11:24
* @Modified_By:
* @Project: Servlet 应用
*/
public class LoginServlet extends HttpServlet {
/*
* HttpServletRequest:请求对象
* HttpServletResponse:响应对象
* */
//处理 get 请求
@Override
protected void doGet(HttpServletRequest req , HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get-------");
System.out.println("req : " + req);
System.out.println("resp : " + resp);
}
//处理 post 请求
@Override
protected void doPost(HttpServletRequest req , HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post-------");
System.out.println("req : " + req);
System.out.println("resp : " + resp);
}
}
- 在
../web/WEB-INF/web.xml
文档配置映射关系
在<web-app>
添加映射关系
<servlet>
<!-- ⾃定义名称 -->
<servlet-name>No1</servlet-name>
<!--
处理请求的类的完整路径
LoginServlet类在src根路径里
-->
<servlet-class>LoginServlet</servlet-class>
</servlet>
<!-- mapping 表示映射 -->
<servlet-mapping>
<!-- ⾃定义名称 -->
<servlet-name>No1</servlet-name>
<!-- 请求名 -->
<url-pattern>/test</url-pattern>
</servlet-mapping>
标签执行顺序:
- 客户端 请求
- 进入 web.xml 匹配数据
<servlet-mapping>
里的<url-pattern>
标签 内容 与 请求名 进行匹配- 匹配成功后 进行以下匹配 (映射标签)
<servlet-mapping>
里的<servlet-name>
标签 内容 与<servlet>
里的<servlet-name>
标签 内容- 匹配成功后 进行以下匹配 (处理类路径)
<servlet>
里的<servlet-class>
标签 内容 与 src内的路径匹配
- 启动,打开 地址: (以下两个测试)
http://localhost:8080/工程名/访问服务器的路径 http://localhost:8080
Servlet 工作原理
- Servlet容器 将Servlet类载入内存 , 实例调用它具体方法。一个Web应用一个Servlet
- 调用Servlet的Service()方法
ServletRequest对象
(请求对象) 和ServletResponse对象
(响应对象) 都是由Servlet容器
封装好的,直接调用即可 - 每个Servlet都有一个封装Servlet配置的
ServletConfig对象
Servlet 生命周期
1.实例化(使用构造方法创建对象)
2.初始化 init()方法
3.服务 service()方法
4.销毁 destroy()方法
init方法 将会主要完成以下工作:
- 创建用于解析 xml 配置文件的 contextDigester 对象
- 读取默认 context.xml 配置文件,如果存在解析它
- 读取默认 Host 配置文件,如果存在解析它
- 读取默认 Context 自身的配置文件,如果存在解析它
- 设置 Context 的 DocBase
注意:
- 当客户端发送请求,如果 存在servlet对象无需创建,否则新建servlet对象
- 第二次请求时,会判断对象是否存在,但不会执执行init()方法,而直接执行service()方法
- 相应的请求方式,会对应 service方法里的处理方式
Request 请求
HttpServletRequest表示Http环境中的Servlet请求。(扩展了ServletRequest接口)
返回 | 常用方法 | 说明 |
String | getParameter(String name) | 获取 表单指定名称 组件的值 |
String[] | getParameterValues(String name) | 获取 表单指定名称 组件的多个值 |
void | setCharacterEncoding(String env) | 设置 请求的编码类型(针对Post请求) |
RequestDispatcher | getRequestDispatcher(String url) | 跳转 指定页面路径 |
void | setAttribute(String key , String value) | 存储请求属性 |
Object | getAttribute(String key) | 获取 指定属性的返回值 |
请求方式:
- 通过表单 get/post 提交
- 通过 a标签 发送数据
<a href="提交名?key1=value&key2=vlaue..">提交</a> <a href="/test?name=sans&age=12">提交</a>
- 通过地址栏直接拼接-get请求
- js提交数据-get请求
乱码处理:
- post请求转编码 setCharacterEncoding(“UTF-8”);
- get请求 转编码 (方法1)
//针对于get提交时中⽂乱码 String s=new String(变量名.getBytes("ISO-8859-1"),"UTF-8"); String s=new String(request.getParameter("key").getBytes("ISO-8859-1"),"GBK");
- get请求 转编码 (方法2)
在Tomcat目录/conf/server.xml
设置字符集<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />
get和post区别:
get请求: 该请求会附加在URL之后,从
?
开始以&
分割变量和属性。url采用的是ASCLL编码。post请求: 该请求数据置放在HTTP请求包的包体中进行传输数据。
数据传输大小
get会受到url的长度限制,而post不会安全性
提交/进入 时,get会在url后面显示,而post不会
实例:
html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>!!!</title>
</head>
<body>
<a href="requestTest?click=true&summary=用户点击了超链接">超链接测试</a>
<form action="requestTest" method="post">
uname:<input type="text" name="username"><br>
upassword:<input type="password" name="userpassword"><br>
sex:
<input type="radio" name="sex" value="man">男
<input type="radio" name="sex" value="woman">女
<br>
hobby:
<input type="checkbox" name="hobby" value="basketball">篮球
<input type="checkbox" name="hobby" value="football">足球
<input type="checkbox" name="hobby" value="tennis">网球
<br>
<input type="submit">
</form>
</body>
</html>
Java获取
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author: 柏竹
* @Description: 一个简洁主义...
* @Date_Created_in: 2021-04-10 9:39
* @Modified_By:
* @Project:
*/
public class MyRequestTest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req , HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Get=========");
System.out.println("超链接点击了?"+req.getParameter("click"));
System.out.println("摘要:"+req.getParameter("summary"));
}
@Override
protected void doPost(HttpServletRequest req , HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Post=========");
//解决乱码
req.setCharacterEncoding("utf-8");
String name = req.getParameter("username");
String password = req.getParameter("userpassword");
String sex = req.getParameter("sex");
String[] hobbys = req.getParameterValues("hobby");
System.out.println("UserName:"+name);
System.out.println("UserPassword:"+ password);
System.out.println("sex:"+ sex);
if (hobbys != null || hobbys.length != 0){
System.out.println("hobby:");
for (String tmp : hobbys) {
System.out.println(tmp);
}
}
//存值
req.setAttribute("username",name);
req.setAttribute("userpassword",password);
//取值
System.out.println("取值测试:");
System.out.println(req.getAttribute("username"));
//跳转页面 (提交跳转的页面 在web文件夹下subTest.html)
req.getRequestDispatcher("/subTest.html").forward(req,resp);
}
}
Response 响应
HttpServletResponse 表示 Servlet响应,继承了ServletResponse接口,专门用来封装HTTP响应消息。
返回 | 常用方法 | 说明 |
void | addCookie(Cookie cookie) | 指定 cookie添加到响应中 |
void | sendRedirect(String location) | 指定 重定向URL位置(页面跳转) |
PrintWriter | getWriter() | 获取 可以给前端输出的字符流对象 |
void | setContentType(String type) | 设置 响应的内容类型 |
重定向与转发的区别
- 重定向 会改变地址,requset存储的数据会丢失
转发 时地址会显示请求页面的地址,保存了页面的数据- 重定向 两次请求 两次响应;转发 一次请求 一次响应
- js 跳转页面,也会丢失 requset存储的数据
Session 会话
session是服务器端使用的一种记录客户端状态的机制。(是ServletRequest的扩展)
sessinon可有多个页面、多个request(请求),重定向也不会丢失数据。
当浏览器访问Web服务器时,Servlet容器就会创建一个Session对象和ID属性,当客户端后续访问服务器时,只要将ID标识号传递给服务器,服务器就能判断该请求是哪个客户端发送的,从而选择与之对应的Session对象为其服务。
更多ServletRequest方法更多HttpServletRequest方法更多HttpSession方法
返回 | 常用方法 | 说明 |
HttpSession | getSession() | 获取 请求的Session对象 |
void | setAttribute(String key , Object value) | 以key/value存储属性值 |
Object | getAttribute(String key) | 获取 指定key的属性值,没有则null |
void | invalidate() | 设置 session 无效,取消任何会话的对象 |
String | getid() | 获取 当前 会话ID标识号 |
void | setMaxInactiveInterval(int interval) | 设置 会话有效时长 ,超出时长则无效会话(单位:秒) |
void | removeAttribute(String key) | 从此会话 删除 指定key的值(置为null) |
会话有效时长:
- setMaxInactiveInterval(int second) //指定秒数有效
- 编辑
web.xml
<session-config> <session-timeout>10</session-timeout>//单位:分钟 </session-config>
session失效方式:
- invalidate()
- removeAttribute(“key”);
- 直接关闭浏览器
Servlet 初始化参数
在 web.xml
中配置 Servlet 时,可以配置初始化参数
Servlet可通过 ServletConfig接口
提供的方法来获取这些参数
servlet局部参数配置
在 web.xml
中对应的 servlet 添加 init-param属性
(获取参数仅限于配置的servlet)
<init-param>
<param-name>key</param-name>
<param-value>value</param-value>
</init-param>
servlet全局部参数配置
在 web.xml
中添加 context-param属性
(全部servlet都可获取)
<context-param>
<param-name>key</param-name>
<param-value>value</param-value>
</context-param>
获取数据
- 请求 -> init() -> …
servlet中 重写init()方法,通过以下代码获取 (全局和局部获取方式不一样)
@Override
public void init(ServletConfig config) throws ServletException {
//匹配指定name 获取 对应的值
//局部
String vlaue = config.getInitParameter("key") );
//全局
String vlaue2 = config.getServletContext().getInitParameter("allKey") );
}
- 请求 -> init() -> servlet() -> doGet()/doPost() -> …
//超链接响应获取
@Override
protected void doGet(HttpServletRequest req , HttpServletResponse resp) throws ServletException, IOException {
//局部
String vlaue = this.getInitParameter("key");
//全局
String vlaue2 = this.getInitParameter("allKey");
String vlaue3 = this.getServletContext().getInitParameter("allKey");
}
注意: 不同的获取方式不能共存!!!
Servlet 注解
注解 提供的信息,让开发更便捷易懂
属性 | 类型 | 必须 | 说明 |
asyncSupported | boolean | F | Servlet是否支持异步操作 |
displayName | String | F | Servlet显示名称 |
initParams | webInitParam[] | F | 配置初始化参数 |
loadOnStartup | int | F | Servlet 的优先级 加载(越小越早) |
name | String | F | 指定Servlet名称 |
urlPatterns/value | String[] | T | 两个属性作用相同,指定处理的url |
urlPatterns匹配说明
完全匹配
/test/userList.action
匹配绝对路径的请求路径匹配
/test/*
匹配test路径下的所有请求扩展名匹配
*.action
匹配后缀为action 结尾的请求
注意:
- 如果当前Servlet注解了就无需再配置
web.xml
- name若不指定值,则默认以类名为name
- urlPatterns路径分割不需有斜杠
/
- urlPatterns可映射多个路径
@WebServlet(
name = "No.6",
//完全路径;全局路径匹配;扩展名匹配
// /test/no1/index.css
// /test/* ; /test/no1/*
// *.css
urlPatterns = "/test/no1/*",
initParams = {
@WebInitParam(name = "name",value = "zhangsan")
},
loadOnStartup = 1
)
public class AnnotationTest extends HttpServlet {
···
}
完整测试
点击个人项目下载测试