Servlet
Servlet
什么是Servlet
- 概念:Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其 他 HTTP客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
- 定位:Java Servlet用Java编写的服务器端程序(web application)。
- 作用:其主要功能在于交互式地浏览和修改数据,生成动态Web内容。
- 理解:狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,我们将Servlet理解为后者。
理解servlet原理
- 浏览器通过url找到对应的项目
- 在mapping中找到对应的servlet名称
- mapping中的servlet-name对应到了servlet中的servlet-name
- servlet-name就找到了对应的实现类,用来把前端传来的请求进行处理最后在前端页面上响应
Servlet生命周期
resquest中常见的方法
getParameter(String name)方法 和 getQueryString()方法的区别
- getParameter(String name)方法可以获取到get/post请求的参数
- getQueryString()方法只能获取到get请求的参数
getMethod、getRequestURI、getContentType方法测试
public class MyRequestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 编码和数据类型
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
//获取请求方法类型
String method = request.getMethod();
//获取相对地址信息
String uri = request.getRequestURI();
//
String contentType = request.getContentType();
PrintWriter writer = response.getWriter();
writer.println(String.format("<h1>method:%s</h1><p></p>",method));
writer.println(String.format("<h1>uri:%s</h1><p></p>",uri));
writer.println(String.format("<h1>contentType:%s</h1><p></p>",contentType));
}
}
<!--req常用信息-->
<servlet>
<servlet-name>myrequest</servlet-name>
<servlet-class>MyRequestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myrequest</servlet-name>
<url-pattern>/req</url-pattern>
</servlet-mapping>
reponse常见方法
时钟表
用setIntHeader()实现
public class RefreshServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 编码和数据类型
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
//每秒刷新一次
response.setIntHeader("Refresh",1);
PrintWriter writer = response.getWriter();
writer.println(String.format("<h1>当前时间:%s</h1>",new Date()));
}
}
<!--定时刷新器-->
<servlet>
<servlet-name>refresh</servlet-name>
<servlet-class>RefreshServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>refresh</servlet-name>
<url-pattern>/ref</url-pattern>
</servlet-mapping>
会一直刷新时间
实现页面跳转的两种方式
setStatus和setHeader
sendRedirect
public class LocationServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 编码和数据类型
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
//实现跳转方式1
//response.setStatus(301);
//response.setHeader("location","https://www.baidu.com/");
response.sendRedirect("https://www.baidu.com/");
}
}
<!--跳转-->
<servlet>
<servlet-name>location</servlet-name>
<servlet-class>LocationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>location</servlet-name>
<url-pattern>/local</url-pattern>
</servlet-mapping>
Servlet上传文件
前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图片上传</title>
</head>
<body>
<form method="post" action="upload" enctype="multipart/form-data">
<input name="myfile" type="file">
<p></p>
<input type="submit" value="提交">
</form>
</body>
</html>
接口实现
<!--文件上传-->
<servlet>
<servlet-name>upload</servlet-name>
<servlet-class>MyUploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
后端代码
@MultipartConfig
public class MyUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 编码和数据类型
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
//全球唯一ID
UUID uuid = UUID.randomUUID();
//保存图片
Part part =request.getPart("myfile");
//保存图片
part.write(String.format("D:\\%s%s",uuid,part.getSubmittedFileName()));
PrintWriter writer = response.getWriter();
writer.println("<h1>图片保存成功</h1>");
}
}
选择文件并提交
可以看到在我设置的目录下存储了名字叫b的一样的图片
文件上传注意事项:
- 写入文件不要写入系统盘(C),可能会写入失败,因为权限不够
- 写入目录不要有中文
- 写入的文件名不能是一个固定重复的文件(会导致文件覆盖的问题)
时间戳并不能保证并发时的唯一性,我们可以用UUID拿到全球唯一id
Cookie
概念
- 定义: Cookies 是存储在客户端计算机上的文本文件,并保留了用户的各种跟踪信息
- 作用: 会话保持,如完成用户的登录与状态保持
工作原理
- 客户端向服务区发起登录请求
- 服务器脚本向浏览器发送一组 Cookies。例如:姓名、年龄或识别号码等。
- 浏览器将这些信息存储在本地计算机上,以备将来使用。
- 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookies 信息发送到服务器,服 务器将使用这些信息来识别用户。
存储cookie
<!--存储cookie-->
<servlet>
<servlet-name>setcookie</servlet-name>
<servlet-class>SetCookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>setcookie</servlet-name>
<url-pattern>/setcookie</url-pattern>
</servlet-mapping>
public class SetCookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
//cookie代码写入
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 编码和数据类型
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
//创建cookie
Cookie usernameCookie = new Cookie("username","java");
//设置cookie的最大存活时间
usernameCookie.setMaxAge(60); //最大存活时间60s
//用来告诉客户端存储cookie信息
response.addCookie(usernameCookie);
//永久cookie
Cookie pwdCookie = new Cookie("pwd","pwd");
pwdCookie.setMaxAge(-1);
response.addCookie(pwdCookie);
//打印cookie存储成功
PrintWriter writer = response.getWriter();
writer.println("<h1>Cookie存储成功</h1>");
}
}
读取cookie
<!--读取cookie-->
<servlet>
<servlet-name>getcookie</servlet-name>
<servlet-class>GetCookieServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getcookie</servlet-name>
<url-pattern>/getcookie</url-pattern>
</servlet-mapping>
public class GetCookieServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 设置编码和返回的类型
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
//读取所有cookie
Cookie[] cookies = request.getCookies();
PrintWriter writer = response.getWriter();
for (Cookie cookie : cookies) {
writer.println(String.format("<h1>Cookie Name:%s,Cookie Valeue:%s</h1>",cookie.getName(),cookie.getValue()));
}
}
}
Cookie的缺点
因为Cookie是存储在客户端(浏览器)所以它有被篡改的风险。
Session
为了解决cookie的敏感信息问题,session则会保存在服务器端
sessionid是密钥,非程序员自己控制,系统自动生成
session访问量
<!--Session-->
<servlet>
<servlet-name>sess</servlet-name>
<servlet-class>SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sess</servlet-name>
<url-pattern>/sess</url-pattern>
</servlet-mapping>
public class SessionServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 编码和数据类型
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
//验权(验证用户名和密码是否正确)
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
if(name != null && pwd != null && name.equals("root") && pwd.equals("111111")) {
//用户效验成功,创建会话信息
//尝试从客户端获取Session,如果获取不到则创建一个会话信息;false:不会新创建一个会话信息
HttpSession session = request.getSession(true); //一定会有一个会话信息
String sessionId = session.getId();
writer.println("<h1>欢迎访问~</h1>");
writer.println(String.format("<h3>SessionID:%s</h3>",sessionId));
//session存储访问数量的key
String countKey = "countkey";
if(session.isNew() || session.getAttribute(countKey) == null) {
session.setAttribute(countKey,1);
writer.println("<h4>访问次数:1</h4>");
} else {
int count = (int)session.getAttribute(countKey);
count++;
//重新将访问数据变更到
session.setAttribute(countKey,count);
writer.println(String.format("<h4>访问次数:%d</h4>",count));
}
} else {
writer.println("<h1>用户名或密码错误!</h1>");
}
}
}
Session持久化
session是直接存储在指定服务器的内存中的,一般使用够了,但是在集群场景当中,可能
需要通过session共享,来保证用户在不同的服务器上都可以得到认证。
简单的说:将session保存在服务器数据库或者文件中的行为称之为session持久化
内存特性:操作速度快,但是数据在重启之后就会丢失。
磁盘特性:操作速度慢,但是它的数据一致保存
cookie vs session
两者有什么区别呢?
- Cookie以文本文件格式存储在浏览器中,而session存储在服务端
- 因为每次发起 Http 请求,都要携带有效Cookie信息,所以Cookie一般都有大小限制,以防止增加 网络压力,一般不超过4k
- 可以轻松访问cookie值但是我们无法轻松访问会话值,因此session方案更安全