1.会话技术
- 会话:一次会话中包含多次请求和响应
- 一次会话:浏览器第一次给服务器发送请求,会话建立,直到有一方断开为止
- 功能:在一次会话的范围内的多次请求间,共享数据
- 方式:
- 客户端会话技术:Cookie
- 服务器端会话技术:Session
1.1 Cookie
概念:客户端会话技术,把数据保存到客户端
使用步骤:
- 创建Cookie对象,绑定数据
- new Cookie(String name, String value)
- 发送Cookie对象
- response.addCookie(Cookie cookie)
- 获取Cookie,拿到数据
- Cookie[] request.getCookies()
@WebServlet("/CookieDemo1")
public class CookieDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie c = new Cookie("msg", "hello");
response.addCookie(c);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet("/CookieDemo2")
public class CookieDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
if(cookies != null) {
for(Cookie c : cookies) {
String name = c.getName();
String value = c.getValue();
System.out.println(name + ":" + value);
}
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
注意:
- 默认情况下,当浏览器关闭后,Cookie数据被销毁
- 如需持久化存储:setMaxAge(int seconds)
- 正数:将cookie数据写到硬盘的文件中,持久化存储,数字为存活时间,单位秒
- 负数:默认值
- 零:删除cookie信息
- 如需持久化存储:setMaxAge(int seconds)
- 在tomcat 8 之前,cookie不能直接存储中文信息,需要中文数据转码;8 之后,支持中文数据
- 在同一个tomcat服务器中,部署多个web项目,这些项目中的cookie共享问题
- 默认情况下,cookie不能共享
- setPath(String path):设置cookie的获取范围。默认情况下,设置当前的虚拟目录
- 如需共享,可以将path设置为“/”
- 不同的tomcat服务器之间cookie共享问题
- setDomain(String path):如果设计一级域名相同,那么多个服务器之间cookie可以共享
1.2 Session
概念: 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。
快速入门
- 获取HttpSession对象
- HttpSession session = request.getSession();
- 使用HttpSession对象
- Object getAttribute(String name)
- void setAttribute(String name, Object value)
- void removeAttribute(String name)
Session的实现依赖于Cookie
注意:
- 当客户端关闭后,服务器不关闭,两次获取的Session对象,默认情况下不是同一个
- 若想要相同,则可以创建Cookie,键为JSESSIONID,设置最大存活时间,让cookie持久化保存
...
Cookie cookie = new Cookie("JSESSIONID", session.getId());
cookie.setMaxAge(60 * 60);
response.addCookie(cookie);
...
- 当客户端不关闭,服务器关闭后,两次获取的Session对象不是同一个
- 虽然不是同一个,但是要确保数据不丢失
- session的钝化:在服务器正常关闭之前,将session对象系列化到硬盘上
- session的活化:在服务器启动后,将session文件转化为内存中session对象
- session对象什么时候被销毁
- 服务器关闭
- session对象调用invalidate()
- session的默认失效时间 30分钟
特点:
- session用于存储一次会话的多次请求的数据,存在服务器端
- session可以存储任意类型、任意大小的数据
2. JSP
概念: Java Server Pages,Java服务器端页面。即,一个特殊的页面,既可以指定定义html标签,又可以定义Java代码
原理:
- jsp其实是一种特殊的Servlet
- 当jsp页面第一次被访问时,服务器会把jsp编译成java文件
- 然后再把java编译成.class
- 然后创建该类对象
- 最后调用它的service()方法
- 第二次请求同一jsp时,直接调用service()方法。
脚本:
- <% 代码 %>:定义的java代码,在service方法中,service方法中可以定义什么,该脚本就可以定义什么
- <%= 代码 %>:用于输出,用于输出一条表达式(或变量)的结果。
- <%! 代码 %>:定义的java代码,在jsp转换后的java类的成员位置,用来创建类的成员变量和成员方法
2.1 内置对象
在jsp页面中不需要创建,直接使用的对象
- out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
- response.getWriter()数据输出永远在out.write()之前,因为tomcat服务器真正给服务器做出相应之前,会先找response缓冲区数据,再找out缓冲区数据
- config(ServletConfig):Servlet的配置对象;
- page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象,引用为Object类型;
- pageContext(PageContext):当前页面共享数据,可以用来获取其它八个对象;
- exception(Throwable):异常对象,只有在错误页面中可以使用这个对象;
- request(HttpServletRequest):即HttpServletRequest类的对象,一次请求访问的多个资源(转发);
- response(HttpServletResponse):即HttpServletResponse类的对象,响应对象;
- application(ServletContext):即ServletContext类的对象,所有用户间共享数据;
- session(HttpSession):即HttpSession类的对象,一次会话的多个请求间。不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。
2.2 指令
作用: 用于配置JSP页面,导入资源文件
格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 … %>
分类:
- page:配置JSP页面的
- contentType:等同于response.setContentType(),用于设置响应体的mime类型以及字符集,设置当前jsp页面的编码
- language:指定当前jsp编译后的语言类型(虽然现在只能定义java)
- import:导包
- buffer:缓冲区的大小
- errorPage:当前页面发生异常后,会自动跳转到指定的错误页面
- session:当前页面是否支持session,如果为false,那么当前页面就没有session这个内置对象
- isErrorPage:标识当前页面是否是错误页面
- true:是,可以使用内置对象exception
- false:否,默认值,不可以使用exception
- include: 页面包含的。导入页面的资源文件
- taglib: 导入资源
- <%@ taglib prefix=“前缀,自定义的” uri=“资源地址” %>
2.3 注释
- html注释:
<!-- -->:只能注释html代码片段
- jsp注释
<%-- --%>:可以注释所有
3. MVC开发模式
- M:Model,模型,JavaBean。
- 完成具体的业务操作
- V:View,视图。JSP
- 展示数据
- C:Controller,控制台。Servlet
- 获取用户的输入
- 调用模型
- 将数据交给视图进行展示
请求处理过程
4. EL表达式
作用: 简化和替换jsp页面中java代码的编写
语法: ${ 表达式 }
注意:
- jsp默认支持el表达式
- 如果需要忽略el表达式
- 设置jsp中page指令:isELIgnored=“true”,忽略当前jsp页面中所有的el表达式
- ${ 表达式 }:忽略当前这个el表达式
- 如果需要忽略el表达式
4.1 运算符
- 算数运算符:+、 -、 *、 /(div)、 %(mod)
- 比较运算符:>、 <、 >=、 <=、 ==、 !=
- 逻辑运算符:&&(and)、||(or)、!(not)
- 空运算符:empty,用于判断字符串、集合、数组对象是否为null并且长度是否为0
4.2 获取值
- el表达式只能从域对象中获取值
- 语法:
- ${域名称.键名}:从指定域中获取指定键的值
- 域名称:
- pageScope -> pageContext
- requestScope -> request
- sessionScope -> session
- applicationScope-> application(ServletContext)
- 域名称:
- ${键名}:表示依次从最小的域中查找是否有该键对应的值,直到找到为止
- ${域名称.键名}:从指定域中获取指定键的值
- 获取对象、List集合、Map集合的值
- 对象:${域对象.键名.属性名}
- List集合:${域名称.键名[索引]}
- Map集合:
- ${域名称.键名.key名称}
- ${域名称.键名[“key名称”]}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>el获取对象值</title>
</head>
<body>
<%
people p = new people();
p.setAge(18);
p.setName("张三");
p.setBirthday(new Date());
request.setAttribute("p", p);
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("abc");
request.setAttribute("l", list);
Map map = new HashMap();
map.put("name", "李四");
map.put("people", p);
map.put("gender", "boy");
request.setAttribute("m", map);
%>
<h3>获取对象中的值</h3>
${p.age} <br>
${p.name} <br>
${p.birthday} <br>
${p.birStr} <br>
<h3>获取List集合的值</h3>
${l} <br>
${l[0]} <br>
${l[5]} <br>
<h3>获取Map集合的值</h3>
${m.gender} <br>
${m["name"]} <br>
${m.people.name} <br>
</body>
</html>
隐式对象 pageContext: 可以用来获取jsp其它八个内置对象
- ${pageContext.request.contextPath}:动态获取虚拟目录
5. JSTL
概念: JavaServer Pages Tag Library,JSP标准标签库
作用: 用于简化和替换jsp页面上的Java代码
使用步骤:
- 导入jstl相关jar包
- 引入标签库:taglib指令:<%@ taglib %>
- 使用标签
常用标签:
- if 标签
- 属性:
- test:必须属性,接受boolean表达式(若为if,则显示if标签体内容,若为false,则不显示标签体内容)
- 属性:
- choose 标签(相当于switch)
- 使用choose标签声明
- 使用when标签做判断
- 使用otherwise标签做其它情况的声明
- foreach 标签(相当于for)
- begin:开始值
- end:结束值
- var:临时变量
- step:步长
- varStatus:循环状态对象
- index:容器中元素的索引,从0开始
- count:循环次数,从1开始
- items:容器对象
- var:容器中元素的临时变量
练习
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>test</title>
</head>
<body>
<%
List list = new ArrayList();
list.add(new people("张三", 15));
list.add(new people("李四", 16));
list.add(new people("王五", 17));
request.setAttribute("list", list);
%>
<table border="1" width="500" align="center">
<tr bgcolor="#deb887">
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
<c:forEach items="${list}" var="people" varStatus="s">
<c:if test="${s.count % 2 == 1}">
<tr bgcolor="#7fffd4">
<td>${s.count}</td>
<td>${people.name}</td>
<td>${people.age}</td>
</tr>
</c:if>
<c:if test="${s.count % 2 == 0}">
<tr bgcolor="#deb887">
<td>${s.count}</td>
<td>${people.name}</td>
<td>${people.age}</td>
</tr>
</c:if>
</c:forEach>
</table>
</body>
</html>
6. 三层架构:软件设计架构
分别是表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)、分层的目的是为了高内聚,低耦合、便于更改维护
7. Filter 过滤器
一般用于完成通用的操作。如 登录验证,编码统一处理,敏感字符过滤
可以直接使用 @WebFilter 注解,也可以去web.xml中进行配置
7.1 web.xml配置
<filter>
<filter-name>demo1</filter-name>
<filter-class>cn.itcast.web.Filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<!-- 拦截路径 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
7.2 过滤器执行流程
- 执行过滤器
- 执行放行后的资源
- 执行过滤器放行代码后面的代码
7.3 过滤器生命周期方法
- doFilter:每一次请求被拦截资源时,doFilter方法执行
- init:在服务器启动后,会创建Filter对象,然后调用init方法,只执行一次,用于加载资源
- destroy:在服务器关闭后,Filter对象被销毁,如果服务器是正常关闭,则会执行destroy方法,只执行一次,用于释放资源
7.4 过滤器配置详解
- 拦截路径配置:
- 具体资源路径,即访问指定资源时,过滤器才会被执行
- 拦截目录:/user/*,访问user目录下的所有资源,过滤器都会执行
- 后缀名拦截:*.jsp,访问所有后缀为jsp的资源时,过滤器都会执行
- 拦截所有资源:/*,访问所有资源,过滤器都会执行
- 拦截方式配置:
- 注解配置:
- 设置dispatcherTypes属性
- REQUEST:默认值,浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC :异步访问资源
- 设置dispatcherTypes属性
- web.xml配置
- 设置< dispatcher> < /dispatcher>标签即可
- 注解配置:
7.5 过滤器链
执行顺序: 如果有两个过滤器,1 和 2,则顺序为1 、 2 、 资源执行 、2 、1
过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则进行比较,值小的先执行
- web.xml配置:谁定义在上面,谁先执行
7.6 增强对象的功能
- 装饰模式
- 代理模式
- 概念:
- 真实对象:被代理的对象
- 代理对象
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
- 实现方式:
- 静态代理:有一个类文件描述代理模式
- 动态代理:在内存中形成代理类
- 概念:
动态代理实现步骤:
- 代理对象和真实对象实现相同的接口
- 代理对象 = Proxy.newProxyInstance();
- 使用代理对象调用方法
- 增强方法
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
public class Shop implements SaleComputer {
@Override
public String sale(double money) {
System.out.println("花了" + money + "买了好多东西");
return "零食";
}
@Override
public void show() {
System.out.println("eat...");
}
}
public class ProxyTest {
public static void main(String[] args) {
Shop shop = new Shop();
//动态代理增强shop
/*
三个参数
1. 类加载器:真实对象.getClass().getClassLoader()
2. 接口数组:真实对象.getClass().getInterfaces()
3. 处理器:new InvocationHandler()
*/
SaleComputer proxy_shop = (SaleComputer) Proxy.newProxyInstance(shop.getClass().getClassLoader(), shop.getClass().getInterfaces(), new InvocationHandler() {
/*
代理逻辑编写的方法:代理对象调用的方法都会执行该方法
proxy:代理对象
method:代理对象封装的方法被封装为的对象
args:代理对象调用方法时,传递的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 增强参数
if (method.getName().equals("sale")) {
double money = (double) args[0];
money = money * 0.9;
String obj = (String)method.invoke(shop, money);
System.out.println("送你一包果冻");
return obj + " + 果冻";
} else {
Object obj = method.invoke(shop, args);
return obj;
}
}
});
String sale = proxy_shop.sale(100);
System.out.println(sale);
proxy_shop.show();
}
}
8. Listener 监听器
概念: web的三大组件之一
事件监听机制
- 事件:一件事情
- 事件源:事件发生的地方
- 监听器:一个对象
- 注册监听:将事件、事件源、监听器绑定在一起。当事件源上发生某个事件后,执行监听器代码
8.1 ServletContextListener
ServletContextListener:监听ServletContext对象的创建和销毁
- void contextDestroyed(ServletContextEvent sce):ServletContext对象被销毁之前会调用该方法
- void contextInitialized(ServletContextEvent sce):ServletContext对象创建后会调用该方法
使用步骤:
- 定义一个类,实现ServletContextListener接口
- 复写方法
- 配置
配置
- web.xml:
<listener>
<listener-class>cn.itcast.web.Listener.ContextLoaderListener</listener-class>
</listener>
还可以指定初始化参数< context-param>
- 注解:@WebListener