会话技术
- 会话:一次会话中包含多次请求
- 一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止
- 功能:在一次绘画的范围内的多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务端会画技术:Session
1.Cookie
概念:客户端会话技术,将数据保存到客户端
快速入门:
- 使用步骤:
- 创建cookie对象,绑定数据
- new Cookie(String name , String value)
- 发送cookie对象
- response.addCookie(Cookie cookie)
- 获取Cookie,拿到数据
- Cooke[] request.getCookies()
实现原理
- 基于响应头set-cookie和请求头cookie实现
cookie的细节
一次可不可以发送多个cookie?
可以创建多个Cookie对象,使用response调用多次addCookie方法发送cookie即可
//1.创建CooKie对象 Cookie c1=new Cookie("msg","hello"); Cookie c2=new Cookie("msg","hello"); //2.发送Cookie response.addCookie(c1); response.addCookie(c2);
cookie在浏览器中保存多长时间?
默认情况下,当浏览器关闭后,Cookie数据被销毁
持久化存储:
setMaxAge(int seconds)
//设置cookie的存活时间 c1.setMaxAge(30);//将cookie持久化到硬盘,30秒后会自动删除cookie文件
- 正数:将Cookie数据写到硬盘的文件中,持久化存储。cookie存活时间。
- 负数:默认值。
- 零:删除cookie信息
cooklie能不能存中文?
- 在tomcat8之前 cookie中不能直接存储中文数据
需要将中文数据编码–一般采用URL编码(%E3)- 在tomcat8之后,cookie支持中文数据
cookie获取范围多大?
- 假设在一个tomact服务器中,部署了多个web项目,那么在这些web项目中cookie能不能共享?
- 默认情况下cookie不能共享
- setPath(String path): 设置cookie的获取范围。
- 如果要共享,则可以将Path设置为”/“
- 不同的tomcat服务器间cookie共享问题?
- setDomain(String path):如果设置一级域名相同,那么多个服务器之间cookie可以共享
setDomain(“.baidu.com”),那么tieba.baidu.com和news.baidu.com中cookie可以共享Cookie的特点和作用
- Cookie存储数据在客户端浏览器
- 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20)
- 作用:
- cookie一般用于存储少量的不太敏感的数据
- 在不登陆的情况下,完成服务器对客户端的身份识别
案例:记住上一次访问时间
需求:
- 访问一个servlet,如果是第一次访问,则提示:您好,欢迎您首次访问。
- 如果不是第一次访问,则提示:欢迎回来,您上次访问时间为:显示时间字符串
分析:
可以采用Cookie来完成
在服务器中的Servlet判断是否有一个名为lastTime的cookie
- 有:不是第一次访问
- 响应数据:欢迎回来,您上次访问时间为:上次访问时间
- 写回Cookie:lastTime=访问时间
- 没有:是第一次访问
- 响应数据:您好,欢迎您首次访问
- 写回Cookie:lastTime=访问时间
代码实现
//设置响应的消息体的数据格式以及编码 response.setContentType("text/html;charset=utf-8"); //1.获取所有Cookie Cookie[] cookies = request.getCookies(); boolean flag = false;//没有cookie为lastTime //2.遍历cookie数组 for (Cookie cookie : cookies) { //3.获取cookie的名称 String name = cookie.getName(); //4.判断名称是否是:lastTime if ("lastTime".equals(name)) { //有Cookie,不是第一次访问 flag = true;//有lastTime的cookie //设置cookie的value //获取当年时间的字符串,重新设置cookie的值,重新发送cookie Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String str_date = sdf.format(date); System.out.println("编码前:"+str_date); //URL编码 str_date = URLEncoder.encode(str_date, "utf-8"); System.out.println("编码后:"+str_date); cookie.setValue(str_date); //设置cookie的存活时间 cookie.setMaxAge(60 * 60 * 24 * 30);//一个月 response.addCookie(cookie); //响应数据 //获取cookie的value,时间 String value = cookie.getValue(); System.out.println("解码前:"+value); //URL解码 value= URLDecoder.decode(value,"utf-8"); System.out.println("解码后:"+value); response.getWriter().write("<h1>欢迎回来,您上次访问时间为:" + value + "</h1>"); break; } }
这里使用URL编解码防止空格字符无法转化为cookic数据
if (cookies == null || cookies.length == 0 ||flag==false){ //没有,第一次访问 //设置cookie的value //获取当年时间的字符串,重新设置cookie的值,重新发送cookie Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); String str_date = sdf.format(date); str_date = URLEncoder.encode(str_date, "utf-8"); Cookie cookie=new Cookie("lastTime",str_date); cookie.setValue(str_date); //设置cookie的存活时间 cookie.setMaxAge(60 * 60 * 24 * 30);//一个月 response.addCookie(cookie); response.getWriter().write("<h1>您好,欢迎您首次访问</h1>"); }
2.JSP:入门学习
2.1概念
- Java Server Pages:java服务器端页面
- 可以理解为:一个特殊的页面,其中既可以定义html的标签,又可以定义java代码
- 用于简化书写
2.2原理
- JSP本质上就是一个servlet
2.3JSP的脚本
(JSP定义java代码的方式)
- <% 代码 %>:定义的java代码,在service方法中,service方法中可以定义什么,该脚本就可以定义什么
- <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置。(建议不要使用,容易引发线程安全问题)
- <%= 代码 %>:定义的java代码,会输出到页面上。
2.4JSP的内置对象
-
在jsp页面中不需要获取和创建,可以直接使用的对象
-
jsp一共有9个对象
-
pageContext
-
request
-
session
-
application
-
reponse
-
-
page
-
out:字符输出流对象。可以将数据输出到页面上。和response.getwrite()类似
- response.getwriter()和out.write()的区别
- 在tomcat服务器真正给客户端做出响应之前,会先找response缓冲区数据,再找out缓冲区数据
- response.getwriter()数据输出永远在out.write()之前
-
config
-
exception
变量名 真实类型 作用 pageContext PageContext 当前页面共享数据,还可以获取其他8个内置对象 request HttpServletRequest 一次请求访问的多个资源(转发) session HttpSession 一次会话的多个请求间 application ServletContext 所有用户间共享数据 response HttpServletResponse 响应对象 page Object 当前页面的(Servlet)对象 this out Jspwriter 输出对象,数据输出到页面上 config ServletConfig Servlet的配置对象 exception Throwable 异常对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HlsTqzSG-1622027444539)(D:\Java\Java\03-Javaweb\day16_Cookie&Session\课件资料\课件资料\截图\JSP原理.bmp)]
2.5指令
-
作用:用于配置jsp页面,导入资源文件
-
格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2… %>
-
分类:
-
page :配置JSP页面的
- contentType:等同于response.setContentType()
- 设置响应体的mime类型以及字符集
- 设置当前jsp页面的编码
(只能是高级的IDE才能生效,如果使用低级工具,则需要pageEncoding属性设置当前页面的字符集)
- import:导包
- errorPage:当前页面发生异常后,会自动跳转
- isErrorPage:标识当前页面是否是错误页面。
- true:是,可以使用内置对象exception
- false:否,默认值。不可以使用内置对象exception
- contentType:等同于response.setContentType()
-
include :页面包含的。导入页面的资源文件
-
<%@include file="top.jsp"%>
-
-
taglib : 导入资源
-
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
-
prefix:前缀,自定义的
-
-
2.6注释
- html注释: :只能注释html代码片段,会发送到页面源码中
- jsp注释:
<%-- --%>:可以注释所有,不会发送到页面源码中(推荐)
3.Session:主菜
-
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端对象中。HttpSession
-
快速入门:
-
获取HttpSession对象:
HttpSession session = request.getSession();
-
使用HttpSession对象:
Object getAttribute(String name) void setAttribute(String name, Object value) void removeAttribute(String name)
-
-
原理
- Session的实现是依赖于Cookie的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4cL8r4Kr-1622027444540)(D:\Java\Java\03-Javaweb\day16_Cookie&Session\课件资料\课件资料\截图\Session原理.bmp)]
- Session的实现是依赖于Cookie的。
-
细节:
-
当客户端关闭后,服务器不关闭,两次获取session是否为同一个?
-
默认情况下不是
-
如果需要相同,则可以创建cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存
//期望客户端关闭后,session也能相同 Cookie c=new Cookie("JSESSIONID",session.getId()); c.setMaxAge(60*60); response.addCookie(c);
-
-
客户端不关闭,服务器关闭后,两次获取的session是同一个吗?
- 不是同一个,但是要确保数据不丢失
- session的钝化:
- 在服务器正常关闭之前,将session对象系列化到硬盘上
- session活化:
- 在服务器启动后,将session文件转化为内存中的session对象即可。
-
session的失效时间?
-
服务器关闭
-
session对象调用invalidate().
-
session 默认失效时间 30分钟
选择配置修改
<session-config> <session-timeout>30</session-timeout> </session-config>
-
-
-
session的特点
- session用以存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型,任意大小的数据
- session与Cookie的区别
- session存储数据在服务器端,cookie在客户端
- session没有数据大小限制,Cookie有
- session数据安全,Cookie相对不安全
案例:验证码
- 案例需求:
- 访问带有验证码的登陆界面login.jsp
- 用户输入用户名,密码以及验证码。
- 如果用户名和密码输入有误,跳转到登陆界面,提示:用户名或密码错误
- 如果验证码输入有误,跳转到登陆界面,提示:验证码错误
- 如果全部输入正确,则跳转到主页success.jsp,显示:用户名,欢迎您
- 分析:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aT5Aln2X-1622027444541)(D:\Java\Java\03-Javaweb\day16_Cookie&Session\课件资料\课件资料\截图\登录案例.bmp)]
MVC开发模式
1.jsp演变历史
- 早期只有servlet,只能使用response输出标签数据,非常麻烦
- 后出现了jsp,简化了servlet的开发,如果过度使用jsp,在jsp中即写大量的java代码,有写html表
难于维护,难于分工 - 之后出现了web开发,借鉴mvc开发模式,使得程序的设计更加合理
2.MVC
- M:Modle,模型
- 完成具体的业务操作,如:查询数据库,封装对象
- V:View:视图
- 展示数据
- C:Controller:控制器
- 获取用户的输入(获取请求参数)
- 调用模型
- 将数据交给视图进行展示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FzGLSCHo-1622027444543)(D:\Java\Java\03-Javaweb\day17_EL&JSTL\课件资料\课件资料\截图\MVC开发模式.bmp)]
- 优缺点:
- 优点:
- 耦合性低,方便维护,可以利于分工协作
- 重用性高
- 缺点:
- 使得项目架构变得复杂,对开发人员要求高
- 优点:
EL表达式
- 概念:Expression Language 表达式语言
- 作用:替换和简化jsp页面中java代码的编写
- 语法:$(表达式)
- 注意:
- jsp默认支持el表达式的。如果要忽略el表达式
- 设置jsp中page指令中:isELIgnored=“true”忽略当前jsp页面中所有的el表达式
- $(表达式):忽略当前el表达式
- jsp默认支持el表达式的。如果要忽略el表达式
- 使用:
-
运算:
- 运算符:
- 算出运算符:+ - * / (div) % (mod)
- 比较运算符:> < >= <= == !=
- 逻辑运算符: &&(and) ||(or) !(not)
- 空运算符:empty
- 功能:用于判断字符串、集合、数组对象是否为null并且长度是否为0
- $(empty list)
- $(not empty str):表示判断字符串、集合、数组对象是否不为null 并且 长度>0
- 运算符:
-
获取值
- el表达式只能从域对象中获取值
- 语法:
- ${域名称.键名}:从指定域中获取指定键的值
- 域名称:
- pageScope -->pageContext
- requstScope -->request
- sessionScope -->session
- applicationScope -->applocation(Servlet)
- 举例:在request域中存储了name=张三
获取:$(requestcope.name)
- 域名称:
- ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止。
- ${域名称.键名}:从指定域中获取指定键的值
- 获取对象、List集合、Map集合的值
- 对象:${域名称.键名.属性名}
- 本质上会去调用对象的getter方法
- List集合:${域名称.键名.属性名}
- Map集合:
- ${域名称.键名.Key名称}
- ${域名称.键名[“Key名称”]}
- 对象:${域名称.键名.属性名}
-
隐式对象:
-
el表达式中有11个隐式对象
-
pageContext:
-
获取jsp其他八个内置对象
${pageContext.request.contextPath}:动态获取虚拟目录
-
-
-
JSTL
-
概念:javaserver pages Tag Library JSP标准标签库
是由Apache组织提供的开源的免费的jsp标签 <标签> -
作用:用于简化和替换jsp页面上的java代码
-
使用步骤:
- 导入jstl相关jar包
- 引入标签库:taglib指令:<%@ taglib %>
- 使用标签
-
常用的JSTL标签
-
if :相当于java代码的if语句
- 属性:
- text 必须属性,接受boolean表达式
- 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
- 一边情况下text属性值会结合el表达式一起使用
- text 必须属性,接受boolean表达式
- 注意:
- c:if标签没有else情况,想要else情况,可以再定义一个c:if标签
- 属性:
-
choose :相当于java代码的switch语句
- 使用choose标签声明 相当于switch声明
- 使用when标签做判断 相当于case
- 使用otherwise标签做其他声明 相当于default
-
foreach :相当于java代码的for语句
-
完成重复的操作
for(int i=0;i<10 i++){}-
属性:
begin:开始值
end:结束值
var:临时变量
step:步长
varStatus:循环状态对象
index:容器中的索引,从0开始
count:循环次数 -
<c:forEach begin="1" end="10" var="i" step="1"> ${i}<br> </c:forEach>
-
<c:forEach begin="1" end="10" var="i" step="2" varStatus="s"> ${i}<h3>${s.index}<h3> <h4>${s.count}<h4><br> </c:forEach>
-
-
遍历容器
List<User user:list>{} for(User user:list){}
-
属性:
- items:容器对象
- var:容器中元素的临时变量
- varStatus:循环状态对象
- index:容器中元素的索引,从0开始
- count:循环次数,从1开始
-
<% List list=new ArrayList(); list.add("aaa"); list.add("bbb"); list.add("ccc"); request.setAttribute("list",list); %> <c:forEach item="${list}" var="str" varStatus="s"> ${s.index} $(s.count) $(str)<br> </c:forEach>
-
-
-
-
练习
-
需求:在request域中有一个存有User对象的List集合。
需要使用jstl+el将list集合数据展示到jsp页面的表格table中 -
<% List list = new ArrayList(); list.add(new User("张三",23,new Date())); list.add(new User("李四",24,new Date())); list.add(new User("王五",25,new Date())); request.setAttribute("list",list); %> <table border="1" width="500" align="center"> <tr> <th>编号</th> <th>姓名</th> <th>年龄</th> <th>生日</th> </tr> <%--数据行--%> <c:forEach items="${list}" var="user" varStatus="s"> <c:if test="${s.count % 2 != 0}"> <tr bgcolor="red"> <td>${s.count}</td> <td>${user.name}</td> <td>${user.age}</td> <td>${user.bitStr}</td> </tr> </c:if> <c:if test="${s.count % 2 == 0}"> <tr bgcolor="green"> <td>${s.count}</td> <td>${user.name}</td> <td>${user.age}</td> <td>${user.bitStr}</td> </tr> </c:if> </c:forEach> </table>
-
其中User对象直接调用类的属性或者方法名
-
三层架构:软件设计架构
- 三层架构:
- 页面层(表示层):用户看到的界面。用户可以通过界面上的组件和服务器进行交互
- 业务逻辑层:处理业务逻辑的。
- 数据访问层:操作数据存储文件。
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yA6l9qQY-1622027444544)(D:\Java\Java\03-Javaweb\day17_EL&JSTL\课件资料\课件资料\截图\三层架构.bmp)]
- 案例:用户信息列表展示
Filter:过滤器
-
概念:
- 生活中的过滤器:净水器,空气净化器
- web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
- 过滤器的作用:
- 一般用于完成通用的操作。如:登陆验证,统一验证码处理、敏感字符过滤…
-
快速入门
-
步骤:
-
定义一个类,实现接口Filter
-
复写方法
-
配置拦截路径
-
web.xml
<filter> <filter-name>demo1</filter-name> <filter-class>cn.itcast.Filter.filterDemo1</filter-class> </filter> <filter-mapping> <filter-name>demo1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
注解
@WebFilter("/*")//拦截所有访问资源
-
-
-
代码
public class filterDemo1 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println(123); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filterDemo1被执行了"); //放行 filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { System.out.println(234); } }
-
-
过滤器细节:
-
web.xml配置
<filter> <filter-name>demo1</filter-name> <filter-class>cn.itcast.Filter.filterDemo1</filter-class> </filter> <filter-mapping> <filter-name>demo1</filter-name> <url-pattern>/*</url-pattern> <!-- 拦截路径--> </filter-mapping>
-
过滤器执行流程
- 执行过滤器
- 执行放行后的资源
- 回来执行过滤器放行代码下边的代码
-
过滤器生命周期方法
- init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行依次。用于加载资源
- doFilter:每一次请求被拦截资源时,会执行。(多次执行)
- destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次,用于释放资源
-
过滤器配置详解
- 拦截路径设置:
- 注解配置:
- REQUEST:默认值。浏览器直接请求资源
- FORUARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
- web.xml配置
- 设置标签即可
- 注解配置:
- 拦截路径设置:
-
过滤器链(配置多个过滤器)
- 执行顺序:如果有两个过滤器:过滤器和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
- 过滤器先后顺序问题
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
- 如:AFilter和BFilter,AFilter就先执行
- web.xml配置:谁定义在上边,谁先执行
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
- 增强对象的功能:
- 设计模式:一些通用的解决固定问题的方式
- 装饰模式
- 代理模式
- 概念
- 真实对象:被代理的对象
- 代理对象
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
- 实现方式:
- 静态代理:有一个类文件描述代理模式
- 动态代理:在内存中形成代理类
- 实现步骤:
- 代理对象和展示对象实现相同的接口
- 代理对象=Proxy.newProxyInstance
- 使用代理对象调用方法
- 增强方法
- 增强方式:
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
- 概念
- 设计模式:一些通用的解决固定问题的方式
- 执行顺序:如果有两个过滤器:过滤器和过滤器2
-
Listener:监听器
-
概念:web的三大组件之一。
- 事件监听机制
- 事件:一件事情
- 事件源:事件发生的地方
- 监听器:一个对象
- 注册监听:将事件,事件源,监听器绑定在一起。
当事件源上发生某个时间后,执行监听器代码
- 事件监听机制
-
ServletContextListener:监听ServletContext对象的创建和销毁
-
方法:
- void contextDestroyed(ServletContextEvent sce):ServletContext对象被销毁之前会调用该方法
- void contextInitialialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法
-
步骤:
-
定义一个类,实现ServletContextListener接口
-
复写方法
-
配置
-
web.xml
<listener> <listener-class>cn.itcast.web.ContextLoaderListener</listener-class> </listener>
-
注解
- @webListener
-
-
-
回值类型
3. 增强方法体执行逻辑
Listener:监听器
-
概念:web的三大组件之一。
- 事件监听机制
- 事件:一件事情
- 事件源:事件发生的地方
- 监听器:一个对象
- 注册监听:将事件,事件源,监听器绑定在一起。
当事件源上发生某个时间后,执行监听器代码
- 事件监听机制
-
ServletContextListener:监听ServletContext对象的创建和销毁
-
方法:
- void contextDestroyed(ServletContextEvent sce):ServletContext对象被销毁之前会调用该方法
- void contextInitialialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法
-
步骤:
-
定义一个类,实现ServletContextListener接口
-
复写方法
-
配置
-
web.xml
<listener> <listener-class>cn.itcast.web.ContextLoaderListener</listener-class> </listener>
-
注解
- @webListener
-
-
-