Servlet
1.Servlet 简介
- Servlet是sun公司开发的一个动态web技术
- sun公司在API中提供了一个接口叫Servlet,开发web项目
- 编写一个类,实现Servlet接口
- 把开发的web项目部署到web服务器中
- 把实现了Servlet接口的程序叫做Servlet
- sun公司提供了两个默认的实现类HtppServlet、
2.HelloServlet
搭建一个简单的Servlet环境
-
先构建一个普通的Maven项目,删除掉src目录,以便于建立子工程,这个空的Maven工程就是父工程
-
关于父子工程理解:
父工程中<!-- 这里代表子工程--> <modules> <module>servlet-01</module> </modules>
子工程中
<!-- 代表对应的父工程--> <parent> <artifactId>javaweb-servlet</artifactId> <groupId>com.myl</groupId> <version>1.0-SNAPSHOT</version> </parent>
父工程中配置的环境子工程可以直接使用,反之则不行。
-
Maven环境优化
-
将子工程的web.xml换成最新的(可以去tomcat路径下拿到)
<?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" metadata-complete="true"> </web-app>
-
搭建maven结构完整
-
-
编写一个Servlet程序
- 编写一个普通的JAVA类
- 实现Servlet接口,这里直接继承HttpServlet
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dU161PZR-1615810852633)(C:\Users\10254\AppData\Roaming\Typora\typora-user-images\image-20201118083708896.png)]
package com.myl; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @ClassName: HelloServlet * @Description: TODO * @author: meyolo * @date: 2020/11/18 8:24 */ public class HelloServlet extends HttpServlet { // deGet和doPost方法,可以相互调用,逻辑都一样 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); // 响应流 writer.write("Hello Servlet!"); // 页面输出 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
编写Servlet的映射
原因:我们编写的是一个普通的Java程序,但是要通过浏览器访问则需要连接web服务器,所以我们需要在web服务器中注册我们写的Servlet,还要给一个浏览器访问路径。
<?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" metadata-complete="true"> <!-- 注册Servlet--> <servlet> <servlet-name>hello</servlet-name> </servlet> <!-- 请求Servlet路径--> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
-
配置Tomcat
-
测试启动
3.Servlet原理
4.Mapping映射
-
一个Servlet可以指定一个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello1</url-pattern> </servlet-mapping>
-
一个Servlet可以指定多个映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello2</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello3</url-pattern> </servlet-mapping>
-
一个Servlet可以指定通用映射路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/hello/*</url-pattern> </servlet-mapping>
-
默认路径
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
-
可以指定一些后缀或者前缀等
<servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>*.sad</url-pattern> </servlet-mapping>
-
优先级问题
<servlet> <servlet-name>error</servlet-name> <servlet-class>com.myl.ErrorServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>error</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>
指定了固有的映射路径最高,如果找不到就会走默认的处理请求
5.ServletContext
web容器启动的时候,它会为每个web程序创建一个对应的ServletContext对象,代表了当前的web应用。
1.共享数据
在一个servlet中保存的数据,可以在另一个servlet中拿到。
package com.myl;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName: HelloServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/18 15:21
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// this.getInitParameterNames(); 初始化参数
// this.getServletConfig(); Servlet配置
// this.getServletContext(); Servlet上下文
ServletContext servletContext = this.getServletContext();
String name = "孟哈哈";
// 将数据保存在 servletContext 中,键值对(key,value)
servletContext.setAttribute("name",name);
}
}
package com.myl;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName: GetServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/18 15:41
*/
public class GetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String name = (String) servletContext.getAttribute("name");
resp.setContentType("text/html");
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("你好!"+name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp);
}
}
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>com.myl.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>getc</servlet-name>
<servlet-class>com.myl.GetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>getc</servlet-name>
<url-pattern>/getc</url-pattern>
</servlet-mapping>
2.获取初始化参数
<!-- 配置初始化参数-->
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/blog</param-value>
</context-param>
package com.myl;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName: ServletDemo3
* @Description: TODO
* @author: meyolo
* @date: 2020/11/18 16:12
*/
public class ServletDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
String url = servletContext.getInitParameter("url");
resp.getWriter().println(url);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
3.请求转发
package com.myl;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName: ServletDemo3
* @Description: TODO
* @author: meyolo
* @date: 2020/11/18 16:09
*/
public class ServletDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// 请求转发Servlet
servletContext.getRequestDispatcher("/gp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
4.读取资源文件
Properties:
- 在java目录下新建properties
- 在resources目录下新建properties
都被打包在了一个路径下 classes 我们称这个路径为 classpath
username=myl
userpassword=12345
package com.myl;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @ClassName: ServletDemo5
* @Description: TODO
* @author: meyolo
* @date: 2020/11/22 14:10
*/
public class ServletDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
InputStream resourceAsStream = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/myl/java.properties");
Properties properties = new Properties();
properties.load(resourceAsStream);
String username = properties.getProperty("username");
String userpassword = properties.getProperty("userpassword");
resp.getWriter().println("user"+username+"password"+userpassword);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
<!--build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<!-- 设定主资源目录 -->
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
6.HttpServletRequest
请求转发获取前端传递的参数,并请求转发
package com.myl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
/**
* @ClassName: RequestServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/25 17:27
*/
public class RequestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobbys = req.getParameterValues("hobbys");
System.out.println(username);
System.out.println(password);
System.out.println(Arrays.toString(hobbys));
// 请求转发这里的 / 代表当前web应用的路径
req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
}
7.HttpServletResponse
1.向浏览器输出信息
2.下载文件
- 要获取下载文件的路径
- 下载的文件名
- 设置想办法让浏览器支持下载我们需要的东西
- 获取下载文件的输入流
- 创建缓冲区
- 获取OutputStream对象
- 将FIleOutputStream流写入buffer缓冲区
package com.myl.servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
/**
* @ClassName: FileDownload
* @Description: TODO
* @author: meyolo
* @date: 2020/11/22 15:12
*/
public class FileDownload extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
String realPath = "F:\\javaweb-servlet\\response\\target\\classes\\1.png";
System.out.println("下载文件的路径:"+realPath);
//
// 2. 下载的文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
//
// 3. 设置想办法让浏览器支持下载我们需要的东西,后面的URLEncoder中文文件名编码
resp.setHeader("Content-disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8");
//
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
//
// 5. 创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
//
// 6. 获取OutputStream对象
ServletOutputStream out =resp.getOutputStream();
//
// 7. 将FIleOutputStream流写入buffer缓冲区
while ((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.验证码实现
package com.myl.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* @ClassName: ImageServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/22 16:27
*/
public class ImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 浏览器3秒刷新一次
resp.setHeader("refresh","3");
//在内存中创建一个图片
BufferedImage image = new BufferedImage(100, 30, BufferedImage.TYPE_INT_RGB);
//得到图片
Graphics2D g = (Graphics2D) image.getGraphics();
//设置图片的背景色
g.setColor(Color.cyan);
g.fillRect(0,0,100,30);
//给图片写入数据
g.setColor(Color.black);
g.setFont(new Font(null,Font.BOLD,30));
g.drawString(makeNum(),0,20);
//告诉浏览器,这个请求用图片方式打开
resp.setContentType("image/jpg");
//网站存在缓存,不让存在缓存
resp.setDateHeader("expires",-1);
resp.setHeader("Cache-Control","no-cache");
resp.setHeader("Pragma","no-cache");
//把图片写给浏览器
ImageIO.write(image,"jpg",resp.getOutputStream());
}
private String makeNum(){
Random random = new Random();
String num =random.nextInt(999999)+"";
StringBuffer sb = new StringBuffer();
for (int i=0;i<6-num.length();i++){
sb.append("0");
}
num = sb.toString()+num;
return num;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
4.重定向
public void sendRedirect(String location) throws IOException;
<%--
Created by IntelliJ IDEA.
User: 10254
Date: 2020/11/25
Time: 16:25
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<%--EL表达式取出 当前项目路径,也可手动输入项目名称--%>
<form action="${pageContext.request.contextPath}/login" method="get">
<%--<form action="/response/login" method="get">--%>
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" name="submit">
</form>
</body>
</html>
package com.myl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
import java.io.IOException;
/**
* @ClassName: RedirectServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/25 16:23
*/
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("进入这个请求");
String username = req.getParameter("username");
String password = req.getParameter("password");
System.out.println(username+":"+password);
// 注意这里重定向的路径,最好包含项目名
resp.sendRedirect("/response/success.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
8.重定向与请求转发的区别
相同点:都是跳转页面
不同点:
- 重定向页面URL地址变化 状态码302
- 请求转发URL地址不发生变化 状态码307
- 请求转发可以传递数据
9.Cookie、Session
9.1.Cookie
Cookie是存储在计算机内部的文本文件,由服务器发送给客户端,用来保存用户的信息。
识别用户三个步骤:
- 服务器向浏览器发送一组Cookie
- 浏览器将Cookie保存在计算机文本文件
- 当下一次浏览器请求页面时,浏览器将会把这些Cookie发送给服务器,服务器通过Cookie识别用户
关闭浏览器时,会话结束,Cookie也就清除。
Cookie 解析:
Cookie一般设置在HTTP头信息中:
HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT;
path=/; domain=runoob.com
Connection: close
Content-Type: text/html
其中的Set-Cookie 设置了一些Cookie的基本信息,expires是一个指令,告诉浏览器在指定日期后忘记Cookie,现在大多数浏览器都会设置为 存储Cookie,那么到了指定日期后,Cookie将会自动清除,如果用户的浏览器指向任何匹配Cookie的路径和页面,将会重新发送Cookie到服务器。
Servlet 就能够通过请求方法 request.getCookies() 访问 Cookie,该方法将返回一个 Cookie 对象的数组。
实例:
package com.myl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* @ClassName: CookieServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/27 9:14
*/
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
// 服务器从客户端获取Cookie
Cookie[] cookies = req.getCookies();
//判断Cookie是否存在
if(cookies!=null) {
out.write("你上一次访问的时间是:");
for (int i = 0; i < cookies.length; i++) {
// 遍历Cookie的基本数据信息
Cookie cookie = cookies[i];
if (cookie.getName().equals("LastLoginTime")) {
// 通过Long包装转化为长整型
long LastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(LastLoginTime);
//输出本机时间
out.write(date.toLocaleString());
}
}
}else{
out.write("这是您第一次访问本站");
}
Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
保存Cookie,设置有效期
package com.myl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
/**
* @ClassName: CookieServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/27 9:14
*/
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
// 服务器从客户端获取Cookie
Cookie[] cookies = req.getCookies();
//判断Cookie是否存在
if(cookies!=null) {
out.write("你上一次访问的时间是:");
for (int i = 0; i < cookies.length; i++) {
// 遍历Cookie的基本数据信息
Cookie cookie = cookies[i];
if (cookie.getName().equals("LastLoginTime")) {
// 通过Long包装转化为长整型
long LastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(LastLoginTime);
//输出本机时间
out.write(date.toLocaleString());
}
}
}else{
out.write("这是您第一次访问本站");
}
// Cookie中的信息是 键值对, 此处 更新时间
Cookie cookie = new Cookie("LastLoginTime",System.currentTimeMillis()+"");
// 设置Cookie的有效期为 一天
cookie.setMaxAge(24*60*60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
关闭浏览器重新请求
1606442781290
9.2 Session
Session:
- 服务器会给每一个用户(浏览器)创建一个session
- 一个Session独占一个浏览器,只要浏览器没关闭,Session就存在
- 用户登录之后,整个链接网站都可以访问,例如保护用户的信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6TqoFCY5-1615810852666)(C:\Users\10254\AppData\Roaming\Typora\typora-user-images\image-20201127211137799.png)]
Session中的方法
测试:
session请求
package com.myl.servlet;
import com.myl.pojo.Python;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @ClassName: SessionServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/27 19:52
*/
public class SessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
//往Session里面存储信息 object
session.setAttribute("name","孟永龙");
session.setAttribute("names",new Python("孟永龙",20));
// 得到Session的ID
String sessionId = session.getId();
if(session.isNew()){
resp.getWriter().write("Session创建成功"+sessionId);
}else{
resp.getWriter().write("Session已经在服务器中存在"+sessionId);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
session2请求
package com.myl.servlet;
import com.myl.pojo.Python;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @ClassName: Session2
* @Description: TODO
* @author: meyolo
* @date: 2020/11/27 20:01
*/
public class Session2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
String name = (String) session.getAttribute("name");
Python names = (Python) session.getAttribute("names");
System.out.println(names);
System.out.println(name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
session3
package com.myl.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* @ClassName: Session3
* @Description: TODO
* @author: meyolo
* @date: 2020/11/27 20:07
*/
public class Session3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
HttpSession session = req.getSession();
//移除session中存储的信息
session.removeAttribute("name");
//人为消除session,服务器会立即创建一个新的session
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<session-config>
<!-- 设置session自动消亡时间 分钟为单位-->
<session-timeout>1</session-timeout>
</session-config>
9.3 总结
Cookie : 客户端技术 (请求和响应)
Session: 服务器技术 (保存用户的会话信息,还可以存储一些数据)
Cookie信息一般保存在计算机AppData中
一个网站Cookie是否存在上限:
- 一个Cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个Cookie,最多存放20个Cookie
- Cookie大小有限制40kb
- 浏览器设置上限为300个Cookie
删除Cookie
- 不设置有效期,浏览器关闭,则消失
- 设置有效期为0,关闭
编码解码:
URLEncoder.encode("孟永龙","utf-8");
URLDecoder.decode(cookie.getValue(),"utf-8");
Cookie和Session的区别:
- Cookie是把用户的数据写给浏览器,浏览器保存(保存多个)
- Session是把用户的数据写到独占Session中,服务器保存(保存重要信息,减少资源消耗)
- Session对象由服务器创建
10. JSP
10.1 初识JSP
Java server pages:Java服务器端页面,本质就是Servlet,用于动态页面开发。
特点:
- 写JSP页面和写HTML差不多
- HTML写静态页面,Jsp写动态页面,提供动态数据
10.2 JSP原理
JSP执行:
- 代码和HTML差不多
- 服务器内部的执行
- Tomcat中有一个work目录
- IDEA中使用Tomcat会生成一个work目录
C:\Users\10254.IntelliJIdea2019.3\system\tomcat\Unnamed_Servlet-Cookie-Session\work\Catalina\localhost\Servlet_Session\org\apache\jsp
jsp页面转变成了java类,无论访问jsp资源,都是在访问Servlet
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lMYIFp2f-1615810852682)(C:\Users\10254\AppData\Roaming\Typora\typora-user-images\image-20201128075122084.png)]
HttpJspBase.java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.apache.jasper.runtime;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;
import org.apache.jasper.compiler.Localizer;
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
private static final long serialVersionUID = 1L;
protected HttpJspBase() {
}
public final void init(ServletConfig config) throws ServletException {
super.init(config);
this.jspInit();
this._jspInit();
}
public String getServletInfo() {
return Localizer.getMessage("jsp.engine.info", new Object[]{"2.3"});
}
public final void destroy() {
this.jspDestroy();
this._jspDestroy();
}
public final void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this._jspService(request, response);
}
public void jspInit() {
}
public void _jspInit() {
}
public void jspDestroy() {
}
protected void _jspDestroy() {
}
public abstract void _jspService(HttpServletRequest var1, HttpServletResponse var2) throws ServletException, IOException;
}
JSP本质上就是一个Servlet
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
内部工作:
-
判断请求
-
内置对象
final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; HttpServletRequest HttpServletResponse
-
输出页面前的代码
response.setContentType("text/html;charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out;
-
以上这些对象为JSP内置对象,我们可以直接在JSP页面中使用
在JSP页面中
-
如果是JAVA代码,则生成的Java文件中java代码不变
-
如果是HTML代码,则会转变为相应的java代码
out.write("\r\n"); 输出到前端
11.MVC模式
Model:
- 业务处理:业务逻辑(Service)
- 数据持久层: CRUD(Dao)
View
- 显示数据
- 提供链接发起Servlet请求
Controller (当前阶段 指Servlet)
-
接收用户请求: (req:请求参数、Session信息)
-
交给业务层处理对应的代码
-
控制视图的跳转
登录—>接收用户请求—>处理用户请求(获取用户账号、密码)–>业务层处理判断 事务–>Dao层查询用户—>连接数据库
12.Filter
12.1 过滤器:用来过率网站的请求数据
- 处理中文乱码
- 登录验证
使用:
-
导包(不要导错)
- 包 (javax.servlet)
-
实现Filter接口,重写方法
package com.myl.filter; import javax.servlet.*; import java.io.IOException; /** * @ClassName: CharacterEncodingFilter * @Description: TODO * @author: meyolo * @date: 2020/11/28 10:27 */ public class CharacterEncodingFilter implements Filter { @Override //web服务器启动调用初始化 public void init(FilterConfig filterConfig) throws ServletException { System.out.println("CharacterEncodingFilter初始化"); } /* * Chain : 链 * 1、过滤请求中所有代码,在过滤特定请求时都会执行 * 2、必须要让过滤器继续执行 * chain.doFilter(request,response); * * */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=UTF-8"); System.out.println("CharacterEncodingFilter执行前"); //让我们的请求继续走,如果不写,程序走到这就会被拦截 chain.doFilter(request,response); System.out.println("CharacterEncodingFilter执行后"); } @Override //web服务器关闭调用销毁 public void destroy() { System.out.println("CharacterEncodingFilter销毁"); } }
-
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_4_0.xsd" version="4.0"> <servlet> <servlet-name>ShowServlet</servlet-name> <servlet-class>com.myl.servlet.ShowServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ShowServlet</servlet-name> <url-pattern>/servlet/show</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ShowServlet</servlet-name> <url-pattern>/show</url-pattern> </servlet-mapping> <filter> <filter-name>ShowFilter</filter-name> <filter-class>com.myl.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>ShowFilter</filter-name> <!-- 过滤、servlet下面的任何请求都会被这个过滤器过滤--> <url-pattern>/servlet/*</url-pattern> </filter-mapping> </web-app>
12.2 Filter实现登录拦截
-
用户登录成功后,向Session中放入用户的数据
-
进入主页的时候判断用户是否登录:用过滤器拦截
注意:Session中存的数据,重定向是可以接收到的
HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; Object usersession = request.getSession().getAttribute(Constant.USER_SESSION); if(usersession==null){ response.sendRedirect("/error.jsp"); } chain.doFilter(request,response);
package com.myl.servlet;
import com.myl.utile.Constant;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName: LoginServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/28 16:57
*/
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
//判断用户登录正确
if(username.equals("admin")){
//登录成功,给用户Session中添加一个常量
req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId() );
resp.sendRedirect("/sys/success.jsp");
}else{
resp.sendRedirect("/error.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.myl.servlet;
import com.myl.utile.Constant;
import com.mysql.cj.Session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName: LogoutServlet
* @Description: TODO
* @author: meyolo
* @date: 2020/11/28 16:57
*/
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
//判断用户是否登录,如果登录(不为空),则清除掉Constant.USER_SESSION
//此处如果用 req.getSession().invalidate(); 删除Session 有点暴力,会造成资源消耗
if(user_session!=null){
req.getSession().removeAttribute(Constant.USER_SESSION);
resp.sendRedirect("/login.jsp");
}else{
resp.sendRedirect("/login.jsp");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
package com.myl.filter;
import com.myl.utile.Constant;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName: SysFilter
* @Description: TODO
* @author: meyolo
* @date: 2020/11/28 17:20
*/
public class SysFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
//此处Filter中的req,resp需要先强转成父类HttpServletRequest,HttpServletResponse
//然后调用Session,进行判断
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
Object usersession = request.getSession().getAttribute(Constant.USER_SESSION);
if(usersession==null){
response.sendRedirect("/error.jsp");
}
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
package com.myl.utile;
/**
* @ClassName: Constant
* @Description: TODO
* @author: meyolo
* @date: 2020/11/28 16:58
*/
public class Constant {
//设置常量 多个页面引用,易于维护
public final static String USER_SESSION ="USER_SESSION" ;
}
登录:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<form action="/servlet/login" method="get">
用户名:<input type="text" name="username">
<input type="submit">
</form>
</body>
</html>
登录成功进入主页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1>主页</h1>
<a href="/servlet/logout">注销</a>
</body>
</html>
错误
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>错误</title>
</head>
<body>
<h1>错误</h1>
<h2>没有权限访问或者密码错误</h2>
<a href="/login.jsp">返回登录页面</a>
</body>
</html>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.myl.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.myl.servlet.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/servlet/logout</url-pattern>
</servlet-mapping>
<filter>
<filter-name>SysFilter</filter-name>
<filter-class>com.myl.filter.SysFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SysFilter</filter-name>
<url-pattern>/sys/*</url-pattern>
</filter-mapping>
13.监听器
实现一个监听的方式有N种:
-
新建监听器类
package com.myl.listener; import javax.servlet.ServletContext; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; /** * @ClassName: SessionListener * @Description: TODO * @author: meyolo * @date: 2020/11/28 16:06 */ public class SessionListener implements HttpSessionListener { @Override //一旦创建Session,就会触发这个事件 public void sessionCreated(HttpSessionEvent se) { ServletContext servletContext = se.getSession().getServletContext(); Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount"); System.out.println(se.getSession().getId()); if(onlineCount==null){ onlineCount = new Integer(1); }else{ int count = onlineCount.intValue(); onlineCount = new Integer(count+1); } servletContext.setAttribute("OnlineCount",onlineCount); } @Override //一旦销毁Session,触发这个事件 public void sessionDestroyed(HttpSessionEvent se) { ServletContext servletContext = se.getSession().getServletContext(); Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount"); if(onlineCount==null){ onlineCount = new Integer(0); }else{ int count = onlineCount.intValue(); onlineCount = new Integer(count-1); } servletContext.setAttribute("OnlineCount",onlineCount); } }
-
xml注册
<listener> <listener-class>com.myl.listener.SessionListener</listener-class> </listener>
HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @ClassName: SessionListener
* @Description: TODO
* @author: meyolo
* @date: 2020/11/28 16:06
*/
public class SessionListener implements HttpSessionListener {
@Override
//一旦创建Session,就会触发这个事件
public void sessionCreated(HttpSessionEvent se) {
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
System.out.println(se.getSession().getId());
if(onlineCount==null){
onlineCount = new Integer(1);
}else{
int count = onlineCount.intValue();
onlineCount = new Integer(count+1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
@Override
//一旦销毁Session,触发这个事件
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext servletContext = se.getSession().getServletContext();
Integer onlineCount = (Integer) servletContext.getAttribute("OnlineCount");
if(onlineCount==null){
onlineCount = new Integer(0);
}else{
int count = onlineCount.intValue();
onlineCount = new Integer(count-1);
}
servletContext.setAttribute("OnlineCount",onlineCount);
}
}
- xml注册
<listener>
<listener-class>com.myl.listener.SessionListener</listener-class>
</listener>