Cookie&Session Jsp
1 会话技术
1.1 会话管理概述
1.1.1 会话技术介绍
-
会话:浏览器和服务器之间的多次请求和响应 (一次对话)
- 为了实现一些功能,浏览器和服务器之间可能会产生多次的请求和响应
- 从浏览器访问服务器开始,到访问服务器结束(关闭浏览器、到了过期时间)
- 这期间产生的多次请求和响应加在一起就称之为浏览器和服务器之间的一次会话
-
这里的会话,指的是web开发中的一次通话过程,当打开浏览器,访问网站地址后,会话开始,当关闭浏览器(或者到了过期时间),会话结束
-
会话过程中所产生的一些数据,可以通过会话技术( Cookie 和 Session )保存
- cookie&session到底是干嘛用的呢?
- 存储数据,用户登录状态
- 因为在网站中,有很多界面都是需要登录之后才能操作,为了避免重复登录,我们会在第一次登录成功之后将用户的登录状态存储到会话技术中(cookie,session)
1.1.2 会话管理分类
- Cookie:客户端会话管理技术
- 把要共享的数据保存到客户端。
- 每次请求时,把会话信息带到服务器端,从而实现多次请求的数据共享!
- Session:服务器端会话管理技术
- 本质也是采用客户端会话管理技术。
- 只不过在客户端保存的是一个特殊标识,而共享的数据保存到了服务器端的内存对象中。
- 每次请求时,会将特殊标识带到服务器端,根据这个标识来找到对应的内存空间,从而实现数据共享!
1.2 客户端会话管理技术 ***
1.2.1 Cookie概述
1)Cookie的介绍
-
Cookie:客户端会话管理技术
-
作用:可以保存客户端访问网站的相关内容,从而保证每次访问时先从本地缓存中获取,以此提高效率!
-
Cookie API 介绍
2)Cookie的常见属性
属性名称 | 属性作用 | 是否重要 |
---|---|---|
name | cookie的名称 | 必要属性 |
value | cookie的值(不能是中文) | 必要属性 |
path | cookie的路径 | 重要 |
domain | cookie的域名 | 重要 |
maxAge | cookie的生存时间 | 重要 |
version | cookie的版本号 | 不重要 |
comment | cookie的说明 | 不重要 |
细节
Cookie有大小,个数限制。每个网站最多只能存20个cookie,且大小不能超过4kb。同时,所有网站的cookie总数不超过300个。
当删除Cookie时,设置maxAge值为0。当不设置maxAge时,使用的是浏览器的内存,当关闭浏览器之后,cookie将丢失。设置了此值,就会保存成缓存文件(值必须是大于0的,以秒为单位)。
3)Cookie的方法和添加获取
-
cookie的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-15Fvec5a-1611147930930)(img/cookie方法.png)]
-
Cookie源码
- 添加:HttpServletResponse对象中提供了addCookie()方法
- 获取:HttpServletRequest对象中提供了getCookies()方法
-
补充:为啥是响应对象添加cookie,而获取对象是请求对象?
- 因为,cookie是通过服务器端代码将数据保存在浏览器,所以服务器让浏览器做一件事情,肯定是通过响应
- 而在浏览器存储的数据,要想告诉服务器都有什么,那肯定是通过请求
1.2.2 Cookie的使用
-
需求说明
- 通过 Cookie 记录最后访问时间,并在浏览器上显示出来
-
最终目的
- 掌握 Cookie 的基本使用,从创建到保存到客户端,再到从服务器端获取
-
实现步骤
- 通过响应对象写出一个提示信息
- 创建 Cookie 对象,指定 name 和 value
- 设置 Cookie 最大存活时间
- 通过响应对象将 Cookie 对象添加到客户端
- 通过请求对象获取 Cookie 对象
- 将 Cookie 对象中的访问时间写出、
-
案例:新建项目cookie_demo,配置虚拟目录/cookie,新建类servlet.ServletDemo01
package servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; 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.text.SimpleDateFormat; import java.util.Date; /* Cookie的使用 */ @WebServlet("/servletDemo01") public class ServletDemo01 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=UTF-8"); //1.通过响应对象写出提示信息 PrintWriter pw = resp.getWriter(); pw.write("欢迎访问本网站,您的最后访问时间为:<br>"); //2.创建Cookie对象,用于记录最后访问时间 Cookie cookie = new Cookie("time",System.currentTimeMillis()+""); //3.设置最大存活时间(单位s) cookie.setMaxAge(3600); //4.将cookie对象添加到客户端 resp.addCookie(cookie); //5.获取cookie Cookie[] arr = req.getCookies(); for(Cookie c : arr) { if("time".equals(c.getName())) { //6.获取cookie对象中的value,进行写出 String value = c.getValue(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); pw.write(sdf.format(new Date(Long.parseLong(value)))); } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
- 注意:这里我们为了节省时间,所以在一个Servlet中设置之后,立马又获取了
- 其实可以在一个Servlet中设置,另一个Servlet中获取
-
访问
- 在headers中看到的Data是07:23,这个是xx 时间,我们是东八区的,所以+8小时
- 然后set-cookie中可以看到,设置的cookie是time=xxx
- Max-age是1小时
- Expires过期时间是08:23
-
cookie文件
- cookie是保存在浏览器中的,那浏览器将cookie信息保存到缓存文件中了
1.2.3 Cookie的使用细节
1) 细节介绍
- 数量限制
- 每个网站最多只能有 20 个 Cookie,且大小不能超过 4KB。所有网站的 Cookie 总数不能超过 300 个。
- 名称限制
- Cookie 的名称只能包含 ASCCI 码表中的字母、数字字符。不能包含逗号、分号、空格,不能以 $ 开头。
- Cookie 的值不支持中文。
- 存活时间限制 setMaxAge() 方法接收数字
- 负整数:当前会话有效,浏览器关闭则清除。
- 0:立即清除。
- 正整数:以秒为单位设置存活时间。
- 访问路径限制
- 默认路径:取自第一次访问的资源路径前缀。只要以这个路径开头就能访问到
- 设置路径:setPath() 方法设置指定路径
2) 存活时间案例 ***
-
在上个案例中修改代码
//3.设置最大存活时间 //cookie.setMaxAge(3600); cookie.setMaxAge(0); // 立即清除
-
访问
cookie没了
3) 访问路径限制案例
-
新建ServletDemo02:设置cookie
package servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* Cookie的路径限制 取自第一次访问的资源路径前缀 只要以这个前缀为开头(包括子级路径)。获取到 反之获取不到 */ @WebServlet("/servlet/servletDemo02") public class ServletDemo02 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //创建Cookie并添加 Cookie cookie = new Cookie("username","zhangsan"); cookie.setMaxAge(3600); resp.addCookie(cookie); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
新建ServletDemo03:获取cookie
package servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* Cookie的路径限制 */ @WebServlet("/servlet/servletDemo03") public class ServletDemo03 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取Cookie Cookie[] arr = req.getCookies(); for(Cookie c : arr) { if("username".equals(c.getName())) { String value = c.getValue(); resp.getWriter().write(value); } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
新建ServletDemo04:获取cookie
package servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* Cookie的路径限制 */ @WebServlet("/servlet/aaa/servletDemo04") public class ServletDemo04 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取Cookie Cookie[] arr = req.getCookies(); for(Cookie c : arr) { if("username".equals(c.getName())) { String value = c.getValue(); resp.getWriter().write(value); } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
新建ServletDemo05:获取cookie
package servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /* Cookie的路径限制 */ @WebServlet("/bbb/servletDemo05") public class ServletDemo05 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取Cookie Cookie[] arr = req.getCookies(); for(Cookie c : arr) { if("username".equals(c.getName())) { String value = c.getValue(); resp.getWriter().write(value); } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
访问
-
总结:Cookie的路径限制
-
取自第一次访问的资源路径前缀
-
只要以这个前缀为开头(包括子级路径)就可以获取到
-
反之获取不到
-
1.3 服务端会话管理概述 ***
1.3.1 HttpSession概述
1)HttpSession介绍
-
HttpSession:服务器端会话管理技术
- 本质也是采用客户端会话管理技术
- 只不过在客户端保存的是一个特殊标识,而共享的数据保存到了服务器端的内存对象中
- 每次请求时,会将特殊标识带到服务器端,根据这个标识来找到对应的内存空间,从而实现数据共享
- 是 Servlet 规范中四大域对象之一的会话域对象
- 作用:可以实现数据共享
- 为了防止在 一次会话中,让用户多次登录(用户登录状态)
-
域对象API
-
补充:
-
HttpSession,它虽然是服务端会话管理技术的对象,但它本质仍是一个Cookie
-
是一个由服务器自动创建的特殊的Cookie,Cookie的名称就是JSESSIONID,Cookie的值是服务器分配的一个唯一的标识
-
当我们使用HttpSession时,浏览器在没有禁用Cookie的情况下,都会把这个Cookie带到服务器端,然后根据唯一标识去查找对应的HttpSession对象,找到了,我们就可以直接使用了
-
2)HttpSession的常用方法
3)HttpSession的获取
- 获取HttpSession是通过HttpServletRequest接口中的两个方法获取的,如下图所示:
- 这两个方法的区别:
1.3.2 HttpSession的使用
-
需求说明
- 通过第一个 Servlet 设置共享数据用户名,并在第二个 Servlet 获取到
-
最终目的
- 掌握 HttpSession 的基本使用,如何获取和使用
-
实现步骤
- 在第一个 Servlet 中获取请求的用户名
- 获取 HttpSession 对象
- 将用户名设置到共享数据中
- 在第二个 Servlet 中获取 HttpSession 对象
- 获取共享数据用户名
- 将获取到用户名响应给客户端浏览器
-
案例:
- 新建项目session_demo,虚拟目录/session
- 新建servlet.ServletDemo01:设置共享数据
package servlet; 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 javax.servlet.http.HttpSession; import java.io.IOException; /* Session的基本使用 */ @WebServlet("/servletDemo01") public class ServletDemo01 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.获取请求的用户名 String username = req.getParameter("username"); //2.获取HttpSession的对象 HttpSession session = req.getSession(); //3.将用户名信息添加到共享数据中 session.setAttribute("username",username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
新建ServletDemo02:获取共享数据
package servlet; 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 javax.servlet.http.HttpSession; import java.io.IOException; /* Session的基本使用 */ @WebServlet("/servletDemo02") public class ServletDemo02 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.获取HttpSession对象 HttpSession session = req.getSession(); System.out.println(session); System.out.println(session.getId()); //2.获取共享数据 Object username = session.getAttribute("username"); //3.将数据响应给浏览器 resp.getWriter().write(username+""); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
访问
-
验证:demo1和demo2的session是否是同一个对象
//两个代码中都添加如下log System.out.println(session); System.out.println(session.getId());
-
访问:分别访问两个demo,发现一致
1.3.3 细节 (了解)
1) 唯一标识查看
-
唯一标识查看(可以通过Network查看)
2) 禁用cookie
-
浏览器禁用 Cookie之后如何使用session?(用户可以设置浏览器来禁止Cookie的使用)
- 方式一:通过提示信息告知用户,大部分网站采用的解决方式。(推荐) ***
- 方式二:访问时拼接 jsessionid 标识,通过 encodeURL() 方法重写地址。(了解)
-
如何禁用cookie?
浏览器设置–
-
案例:新建ServletDemo03
package servlet; 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 javax.servlet.http.HttpSession; import java.io.IOException; /* Cookie的禁用 */ @WebServlet("/servletDemo03") public class ServletDemo03 extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.获取HttpSession对象 HttpSession session = req.getSession(); System.out.println(session); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
访问
- 在demo1中,创建了一个session
- 在demo3中,因为禁用cookie了,sessionid没有传递过来,所以又创建了一个新session
- 所以俩session不一致
- 为了能够看到效果,我们修改一下代码
-
修改
HttpSession session = req.getSession(false);//改为false,如果没有找到session也不创建
-
访问
-
增加解决呢?看下天猫,也是简单的给出了提升
-
我们也增加提示
if(session == null) { resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().write("为了不影响正常的使用,请不要禁用浏览器的Cookie~"); }
-
访问
- 弹框是需要用到js,后续才学习
-
方式二:访问时拼接 jsessionid 标识,通过 encodeURL() 方法重写地址
//修改demo1 //实现url重写 相当于在地址栏后面拼接了一个jsessionid(encodeURL自动会给路径后添加jsessionid) resp.getWriter().write("<a href='"+resp.encodeURL("http://localhost:8080/session/servletDemo03")+"'>go servletDemo03</a>");
-
访问
-
方式二不推荐,因为每次跳转都的做url重新,比较麻烦
3) HttpSession的钝化和活化
-
什么是钝化和活化
- 钝化:序列化。把长时间不用,但还不到过期时间的 HttpSession 进行序列化,写到磁盘上
- 活化:相反的状态
-
何时钝化
-
第一种情况:当访问量很大时,服务器会根据 getLastAccessTime 来进行排序,
对长时间不用,但是还没到过期时间的 HttpSession 进行序列化。
-
第二种情况:当服务器进行重启的时候,为了保持客户 HttpSession 中的数据,也要对其进行序列化
-
-
注意
- HttpSession 的序列化由服务器自动完成,我们无需关心
2 页面技术
2.1 JSP基础
2.1.1 JSP介绍***
-
JSP(Java Server Pages):是一种动态网页技术标准
-
JSP 部署在服务器上,可以处理客户端发送的请求,并根据请求内容动态的生成 HTML、XML 或其他格式文档的 Web 网页,然后再响应给客户端
-
JSP 是基于 Java 语言的,它的本质就是 Servlet
- 动态资源:会变化的数据
- 动态效果:例如界面上的一些特效,弹框
2.1.2 JSP快速入门
-
创建一个 web 项目:jsp_demo,虚拟目录/jsp
-
在 web 目录下创建一个 index.jsp 文件
- 默认就有一个index.jsp
-
在文件中写一句内容为:这是我的第一个jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>JSP</title> </head> <body> <h1>这是我的第一个jsp</h1> </body> </html>
-
部署并启动项目
-
通过浏览器测试
2.1.3 JSP的执行过程 ***
- 执行过程图
- 明确JSP就是一个Servlet,是一个特殊的Servlet
- 其实在第五步,翻译jsp文件,就是将jsp翻译成了一个Servlet
2.1.4 JSP的.java文件内容分析
-
生成的 java 文件目录
-
C:\Users\13700.IntelliJIdea\system\tomcat_ideaproject\work\Catalina\localhost\jsp\org\apache\jsp
-
JSP 本质就是一个 Servlet
-
补充:HttpJspBase.class反编译查看
2.2 JSP应用
2.2.1 JSP语法
-
JSP 注释
<%-- 注释的内容 --%>
-
Java 代码块
<% Java代码 %>
-
JSP 表达式
<%=表达式%>
-
JSP 声明
<%! 声明变量或方法 %>
-
案例:新建web/jsp语法.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>jsp语法</title> </head> <body> <%-- 1. 这是注释 --%> <%-- 2.java代码块 *** System.out.println("Hello JSP"); 普通输出语句,输出在控制台 out.println("Hello JSP");out是JspWriter对象,输出在页面上 --%> <% System.out.println("Hello JSP"); out.println("Hello JSP<br>"); String str = "hello<br>"; out.println(str); %> <%-- 3.jsp表达式 *** 语法糖:某种语法的简写形式 <%="Hello"%> 相当于 out.println("Hello"); --%> <%="Hello<br>"%> <%-- 4.jsp中的声明(变量或方法) 如果加! 代表的是声明的是成员变量(service中的局部变量) 如果不加! 代表的是声明的是局部变量 *** --%> <%! String s = "abc";%> <% String s = "def";%> <%=s%> <%! public void getSum(){}%> <%--<% public void getSum2(){}%> 这个是局部方法,相当于是在getSum里再声明方法,所以不允许--%> </body> </html>
2.2.2 JSP指令
1)page指令
- 语法:<%@ page 属性名=属性值 属性名=属性值 … %>
-
language: 告知引擎,脚本使用的是java,默认是java,支持java。不写也行。
-
import:告知引擎,导入哪些包(类)。 ***
- 注意:引擎会自动导入:java.lang.*,javax.servlet.*,javax.servlet.http.*,javax.servlet.jsp.
导入的形式:
<%@page import=”java.util.Date,java.util.UUID”%>或者:
<%@page import=”java.util.Date”%>
<%@page import=”java.util.UUID”%> 用:Alt+回车 自动导入
-
contentType:告知引擎,响应正文的MIME类型。contentType=“text/html;charset=UTF-8”
- 相当于response.setContentType(“text/html;charset=UTF-8”);
-
案例:新建jsp指令.jsp
<%-- 1.page指令 --%> <%@ page import="java.util.ArrayList"%> <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="/error.jsp" %> <html> <head> <title>jsp指令</title> </head> <body> <% int result = 1 / 0; %> <% ArrayList list = new ArrayList() %> </body> </html>
-
新建error.jsp:上述代码中1/0是错误的语法,所以会跳转到errorPage指定的error.jsp界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>自定义错误页面</title> </head> <body> 不好意思,出错了~~~ </body> </html>
2)include指令
-
通过该指令,可以包含其他页面
-
语法格式:
<%@include file="" %>
- 属性:file,以/开头,就代表当前应用
-
案例
<%-- 1.page指令 --%> <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="/error.jsp" %> <%-- 2.include指令 --%> <%@ include file="/include.jsp"%> <html> <head> <title>jsp指令</title> </head> <body> <%--<% int result = 1 / 0; %>--%> <%=s%> <%--这里用的s是include.jsp中的--%> </body> </html>
-
新建include.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>被包含的页面</title> </head> <body> <% String s = "Hello"; %> </body> </html>
-
访问
3)taglib指令 ***
-
该指令用于引入外部标签库,html标签和jsp标签不用引入
-
语法格式:
<%taglib uri="" prefix=""%>
-
属性:
- uri:外部标签的URI地址
- prefix:使用标签时的前缀
-
tag:标签,lib:library库,prefix:前缀
2.2.3 JSP细节
1)九大隐式对象
- 什么是隐式对象呢?
- 它指的是在jsp中,可以不声明就直接使用的对象
- 它只存在于jsp中,因为java类中的变量必须要先声明再使用
- 其实jsp中的隐式对象也并非是未声明,只是它是在翻译成.java文件时声明的
- 所以我们在jsp中可以直接使用
隐式对象名称 | 类型 | 备注 |
---|---|---|
request | javax.servlet.http.HttpServletRequest | 请求对象 |
response | javax.servlet.http.HttpServletResponse | 相应对象 |
session | javax.servlet.http.HttpSession | Page指令可以控制开关 |
application | javax.servlet.ServletContext | 应用域对象 |
page | Java.lang.Object | 当前jsp对应的servlet引用实例 |
config | javax.servlet.ServletConfig | Servlet配置对象 |
exception | java.lang.Throwable | 异常对象 |
out | javax.servlet.jsp.JspWriter | 字符输出流,相当于printwriter |
pageContext | javax.servlet.jsp.PageContext | 页面域对象 |
2)PageContext对象
简介
- 是 JSP 独有的,Servlet 中没有
- 是四大域对象之一的页面域对象,还可以操作其他三个域对象中的属性(应用域,会话域,请求域)
- 还可以获取其他八个隐式对象
- 生命周期是随着 JSP 的创建而存在,随着 JSP 的结束而消失。每个 JSP 页面都有一个 PageContext对象
常用方法
在上图中,发现没有页面域操作的方法,其实是定义在了PageContext的父类JspContext中,如下图所示:
3)四大域对象
域对象名称 | 范围 | 级别 | 备注 |
---|---|---|---|
PageContext | 页面范围 | 最小,只能在当前页面用 | 因范围太小,开发中用的很少 |
ServletRequest*** | 请求范围 | 一次请求或当期请求转发用 | 当请求转发之后,再次转发时请求域丢失 |
HttpSession*** | 会话范围 | 多次请求数据共享时使用 | 多次请求共享数据,但不同的客户端不能共享 |
ServletContext | 应用范围 | 最大,整个应用都可以使用 | 尽量少用,如果对数据有修改需要做同步处理 |
2.2.4 JSP-MVC模型介绍 ***
-
M(Model):模型。用于封装数据,封装的是数据模型
-
V(View):视图。用于显示数据,动态资源用 JSP 页面,静态资源用 HTML 页面
-
C(Controller):控制器。用于处理请求和响应,例如 Servlet
-
图示
3 综合案例-学生管理系统升级 ***
3.1 案例效果介绍
3.2 登陆功能
-
创建一个 web 项目:student_manage,虚拟目录/stu
-
在 web 目录下创建一个 index.jsp(默认就有)
-
在页面中获取会话域中的用户名,获取到了就显示添加和查看功能的超链接,没获取到就显示登录功能的超链接
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>学生管理系统首页</title> </head> <body> <%-- 获取会话域中的数据 如果获取到了则显示添加和查看功能的超链接 如果没获取到则显示登录功能的超链接 --%> <% Object username = session.getAttribute("username"); if(username == null) { %> <a href="/stu/login.jsp">请登录</a> <%} else {%> <a href="/stu/addStudent.jsp">添加学生</a> <a href="/stu/listStudentServlet">查看学生</a> <%}%> </body> </html>
-
在 web 目录下创建一个 login.jsp:实现登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>学生登录</title> </head> <body> <form action="/stu/loginStudentServlet" method="get" autocomplete="off"> 姓名:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> <button type="submit">登录</button> </form> </body> </html>
-
创建 LoginStudentServlet,获取用户名和密码
-
如果用户名为空,则重定向到登录页面
-
如果不为空,将用户名添加到会话域中,再重定向到首页
package servlet; 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("/loginStudentServlet") public class LoginStudentServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.获取用户名和密码 String username = req.getParameter("username"); String password = req.getParameter("password"); //2.判断用户名 if(username == null || "".equals(username)) { //2.1用户名为空 重定向到登录页面 resp.sendRedirect("/stu/login.jsp"); return; } //2.2用户名不为空 将用户名存入会话域中 req.getSession().setAttribute("username",username); //3.重定向到首页index.jsp resp.sendRedirect("/stu/index.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
- 访问
3.3 添加功能
-
在 web 目录下创建一个 addStudent.jsp,实现添加学生的表单项
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>添加学生</title> </head> <body> <form action="/stu/addStudentServlet" method="get" autocomplete="off"> 学生姓名:<input type="text" name="username"> <br> 学生年龄:<input type="number" name="age"> <br> 学生成绩:<input type="number" name="score"> <br> <button type="submit">保存</button> </form> </body> </html>
-
创建 AddStudentServlet,获取学生信息并保存到文件中
-
通过定时刷新功能 2 秒后跳转到首页
package servlet; import bean.Student; 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.BufferedWriter; import java.io.FileWriter; import java.io.IOException; /* 实现添加功能 */ @WebServlet("/addStudentServlet") public class AddStudentServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.获取表单中的数据 String username = req.getParameter("username"); String age = req.getParameter("age"); String score = req.getParameter("score"); //2.创建学生对象并赋值 Student stu = new Student(); stu.setUsername(username); stu.setAge(Integer.parseInt(age)); stu.setScore(Integer.parseInt(score)); //3.将学生对象的数据保存到d:\\stu.txt文件中 BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\stu.txt",true)); bw.write(stu.getUsername() + "," + stu.getAge() + "," + stu.getScore()); bw.newLine(); bw.close(); //4.通过定时刷新功能响应给浏览器 resp.setContentType("text/html;charset=UTF-8"); resp.getWriter().write("添加成功。2秒后自动跳转到首页..."); resp.setHeader("Refresh","2;URL=/stu/index.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
访问
3.4 查看功能
-
创建 ListStudentServlet,读取文件中的学生信息到集合中
-
将集合添加到会话域中
-
重定向到 listStudent.jsp 页面上
package servlet; import bean.Student; 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.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; /* 实现查看功能 */ @WebServlet("/listStudentServlet") public class ListStudentServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1.创建字符输入流对象,关联读取的文件 BufferedReader br = new BufferedReader(new FileReader("d:\\stu.txt")); //2.创建集合对象,用于保存Student对象 ArrayList<Student> list = new ArrayList<>(); //3.循环读取文件中的数据,将数据封装到Student对象中。再把多个学生对象添加到集合中 String line; while((line = br.readLine()) != null) { //张三,23,95 Student stu = new Student(); String[] arr = line.split(","); stu.setUsername(arr[0]); stu.setAge(Integer.parseInt(arr[1])); stu.setScore(Integer.parseInt(arr[2])); list.add(stu); } //4.将集合对象存入会话域中 req.getSession().setAttribute("students",list); //5.重定向到学生列表页面 resp.sendRedirect("/stu/listStudent.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req,resp); } }
-
在 web 目录下创建一个 listStudent.jsp
-
定义表格标签。在表格中获取会话域的集合数据,将数据显示在页面上
<%@ page import="bean.Student" %> <%@ page import="java.util.ArrayList" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>查看学生</title> </head> <body> <table width="600px" border="1px"> <tr> <th>学生姓名</th> <th>学生年龄</th> <th>学生成绩</th> </tr> <% ArrayList<Student> students = (ArrayList<Student>) session.getAttribute("students"); for(Student stu : students) { %> <tr align="center"> <td><%=stu.getUsername()%></td> <td><%=stu.getAge()%></td> <td><%=stu.getScore()%></td> </tr> <%}%> </table> </body> </html>
-
访问:点击查看学生,进入查看学生界面