1. ServletContext对象
1.1 概述
ServletContext 对象代表整个web应用,可以和程序的容器(服务器进行通信)。
1.2 获取该对象
- 通过Request对象获取
- request.getServletContext()
- 通过HttpServlet获取(实际是他的父类实现了该方法)
- this.getServletContext()
演示案例:
@WebServlet("/scd")
public class ServletContextDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
ServletContext servletContext1 = this.getServletContext();
System.out.println(servletContext);
System.out.println(servletContext1);
System.out.println(servletContext == servletContext1);
//两种方式获取的是一个ServletContext对象
}
}
1.3 功能
1. 获取MIME类型:
- MIME 类型:在互联网通信过程中定义的一种文件数据类型
- 格式:大数据类型/小数据类型 比如:text / html , image/jpeg
- 获取:String getMimeType(String file):通过文件名(包含扩展名)获取MIME的值
- 扩展名对应的MIME可以去tomcat — conf - web.xml中查看
演示案例:
@WebServlet("/scd2")
public class ServletContextDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
//定义一个文件名
String fileName = "index.html";
//获取MIME
String mimeType = servletContext.getMimeType(fileName);
System.out.println(mimeType);
}
}
2. 域对象:可以共享数据
-
功能:所有域对象都有该功能
- void setAttribute(String name,Object obj) : 存储数据
- Object getAttitude(String name) : 通过键获取值
- void removeAttribute(String name) : 通过键移除键值对
-
作用域:
最大范围,所有用户的所有数据
演示案例:定义两个Servlet,不经过转发获取数据
@WebServlet("/scd3")
public class ServletContextDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
servletContext.setAttribute("info", "牛逼");
}
}
@WebServlet("/scd4")
public class ServletContextDemo4 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
Object info = servletContext.getAttribute("info");
System.out.println(info);
}
}
3. 获取文件的服务器真实存储路
演示案例:
- 分别在src,web,WEB-INF 下创建a.txt, b.txt , c.txt
- 测试案例
@WebServlet("/scd6")
public class ServletContextDemo6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
//获取web目录下的资源
String realPath = servletContext.getRealPath("/b.txt");
System.out.println(realPath);
//获取WEB-INF下的资源:到文件夹中找对应文件对比着写.
realPath = servletContext.getRealPath("/WEB-INF/c.txt");
System.out.println(realPath);
//src下的文件都会被放到WEB-INF下的classes路径中
realPath = servletContext.getRealPath("/WEB-INF/classes/a.txt");
System.out.println(realPath);
}
}
1.4 文件下载
需求:
1. 在一个html文件中写一个超链接
2. 点击超链接,弹出下载提示框
- 如果超链接的 href属性直接指向图片路径,因为浏览器解析器可以解析图片,所以会直接显示图片而不是下载,但是如果src指向视频,因为浏览器无法解析视频,就会默认的弹出下载框。
3. 下载图片
分析:
需要使用响应头设置资源的打开方式,否则图片无法通过超链接下载
- Content-disposition :attachment ; filename=xxx
步骤:
- 定义页面,编辑超链接href属性,指向Servlet, 传递资源的名称:filename
- 定义servlet
- 获取文件名
- 指定response的响应头:
- Content-disposition :attachment ; filename=xxx
- MIME
- 使用字节输入流加载文件进内存
- 使用ServletContext对象获取实际路径
- 将数据写出到response输出流
演示案例:
-
先在web路径下新建image文件夹,将图片放入该文件夹,再创建一个下载页面:download.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="/book/image/Lucky.jpg">小柯基</a> <a href="/book/downloadServlet?filename=Lucky.jpg">皇后</a> </body> </html>
-
downloadServlet
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取文件名称
String filename = req.getParameter("filename");
//找到文件真实路径
ServletContext servletContext = this.getServletContext();
String path = servletContext.getRealPath("/image/"+filename);
//设置响应头
//MIME类型
String mimeType = servletContext.getMimeType(filename);
resp.setHeader("content-type", mimeType);
//打开方式
resp.setHeader("content-disposition","attachment;filename="+filename);
//获取输入输出流
FileInputStream fis = new FileInputStream(path);
ServletOutputStream outputStream = resp.getOutputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != 0) {
outputStream.write(bytes, 0, len);
}
//释放资源
fis.close();
}
}
2. 会话技术
概述:
一次会话中包含多次请求和相应。并且在会话范围内可以共享数据
会话就和谈话的过程一样,你来我往很多次问答。
功能:
共享技术
分类:
1. 客户端会话技术Cookie
2. 服务器端会话技术:Session
2.1 Cookie
-
概述:客户端会话技术,将数据保存到客户端
-
步骤:
- 创建Cookie对象,绑定参数
- new Cookie(String name ,String value)
- 发送Cookie对象
- reponse . addCookie(String name)
- 获取Cookie对象,拿到对象
- Cookie[] request.getCookies()
2.2 入门案例:
测试案例:
- CookieServlet
@WebServlet("/cookieServlet")
public class CookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取cookie对象
Cookie cookie = new Cookie("msg", "hello");
//发送cookie
resp.addCookie(cookie);
}
}
- CookieServlet2
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;
@WebServlet("/cookieServlet2")
public class CookieServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取cookie
Cookie[] cookies = req.getCookies();
//获取数据,遍历cookie
if (cookies != null) {
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
System.out.println(name+":"+value);
}
}
}
}
通过浏览器分别访问这两个servlet,并且读取cookie中的数据
2.3 原理图
2.4 注意事项
- 一次发送多个cookie
- 创建多个cookie对象,多次调用addCookie()方法
-
Cookie在浏览器中保存多长时间
- 默认清空下,当浏览器关闭,Cookie数据被销毁
- 持久化存储:
- setMaxAge(intt seconds):
- seconds:
- 正数:将Cookie数据写到硬盘文件中,持久化存储 :second具体的数值表示文件存活的时长,以秒为单位。
- 负数:默认值
- 0:删除cookie信息,因为服务器无法直接操作用户电脑。
- seconds:
- setMaxAge(intt seconds):
-
Tomcat 8 版本之前,不能直接存储中文数据。 8版本之后,可以直接存储中文
-
Cookie的获取范围
一个服务器多个web项目
- 默认情况下一个tomcat服务器中,多个web项目中的cookie是不能共享的
- 我们可以方法设置:setPath(“/“),这样cookie就可以共享了
不同tomcat服务器
- 通过setDomain()方法,设置相同的一级域名,那么这些一级域名相同的服务器间cookie可以共享
- tieba.baidu.com baidu.com就是一级域名.
2.5 Cookie的特点
- cookie存储数据在客户端浏览器不安全
- 大小有限制:单个Cookie的大小为 4KB, 同一个域名下的总cookie数 不超过 20 个
2.6 Cookie的作用
- 存储少量,内容不敏感的作用
- 在不登陆的情况下,完成服务器对客户端的身份识别(主要用途)
- 比如:用户在不登陆百度的情况下对百度页面进行的个性化设置信息,会被存储在cookie中,下次访问百度。浏览器带着cookie的信息,百度服务器就可以识别其身份,展示用户个性设置的页面
2.7 练习
**需求:**访问网站时给出上一次登录信息:如果是第一次则显示首次登录。
分析:
1. 可以采用Cookie完成
2. 在服务器中的Servlet判断是否有一个lastTime的cookie
- 有:则不是第一次访问
- 响应数据
- 更新Cookie
- 没有:则是第一次访问
- 响应:欢迎您,您是首次访问
- 添加cookie:lastTime = 当前时间戳
代码实现:
@WebServlet("/cookie3")
public class CookieServlet3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置响应编码集
resp.setContentType("text/html;charset=utf-8");
//1. 获取所有Cookie
Cookie[] cookies = req.getCookies();
boolean flag = false;//标记是否有lastTime
//2.遍历数组
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
//3. 获取cookie名称
String name = cookie.getName();
//4.判断
if ("lastTime".equals(name)) {
//存在,不是第一次访问
//响应数据
String value = cookie.getValue();
resp.getWriter().write("<h1>您上一次访问的时间是:"+value+"</h1>");
//设置新的cookie时间
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String newDate = sdf.format(date);
cookie.setValue(newDate);
//设置cookie存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);//存活一个月
//发送cookie
resp.addCookie(cookie);
flag = true;
}
}
}
//第一次访问
if (cookies == null || cookies.length == 0 || flag == false) {
//设置新的cookie时间
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
String newDate = sdf.format(date);
Cookie cookie = new Cookie("lastTime",newDate);
//设置cookie存活时间
cookie.setMaxAge(60 * 60 * 24 * 30);//存活一个月
resp.addCookie(cookie);
flag = true;
resp.getWriter().write("<h1>您是第一次访问</h1>");
}
}
}
写好之后会报错,因为 时间格式中有一个空格,虽然Tomcat8 之后对于中文字符可以支持,但是对于特殊字符它还是不支持,所以我们需要将Cookie数据转化为URL编码存储,使用URL解码来解析。
所以:我们需要在存储数据前进行URL编码,在获取数据后进行URL解码
3. JSP
3.1 概述:
JSP - Java Server Page : Java 服务器端页面,该页面中可以写html标签,也可以写Java代码。可以简化动态内容书写量
演示案例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
System.out.println("Hello JSP");
%>
<h1>Hello JSP</h1>
</body>
</html>
当你浏览该页面时,页面既能输出html标签,服务器中又能输出
3.2 原理:
JSP页面本质是一个Servlet
因为,能在web服务器运行的java程序肯定是Servlet。我们通过前面的案例也能体会到如果我们通过Servlet的response对象响应静态资源工作量非常大的。所以将动态资源和静态资源统一定义在JSP中,服务器启动后,会将JSP转换成对应的Servlet的class字节码文件。里面的方法就是处理动态资源 和 对静态内容的输出
3.3 脚本:
就是定义了JSP中Java代码的书写方式
<% 代码%>
: 定义的java代码,相当于定义在Servlet中的service()方法中<%! 代码%>
:定义的Java代码,相当于定义在Servlet中的成员位置,即成员变量和成员方法<%= 代码%>
:输出语句,使用JSP的内置对象 Out(后面讲)
演示案例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
System.out.println("Hello JSP");
%>
<%! int i = 10;%>
<% i = 3; %>
<%= i%>
<h1>Hello JSP</h1>
</body>
</html>
效果:
3.4 内置对象:
-
**概述:**直接在JSP页面中,不需要获取和创建,可以直接使用的对象
-
分类:九大内置对象
- request
- response
- session
- out
- page
- application
- pageContext
- config
- exception
内置对象名 真实数据类型 作用 request HttpServletRequest 一次请求中共享数据 response HttpServletResponse 响应对象 session HttpSession 一次会话中共享数据 out JspWriter 输出对象,输出数据到当前页面 page Objcet(this-当前jsp页面) 当前页面的对象 application ServletContext 所有用户间共享数据 pageContext PageContext 当前页面共享数据,还可以获取其他8个内置对像 config ServletConfig Servlet配置对象 exception Throwable 只有异常页面有该对象 -
response.getWriter() 和 out对象输出:由于web服务器的工作机制,对于页面的输出,服务器都会先访问response缓冲区,再访问out缓冲区,所以无论 response.getWriter()的编写位置在哪里,它都会先与out对象的输出。
3.5 Session
-
概念:服务器端会话技术 - HttpSession
-
功能:
- 获取HttpSession对象
- request.getSession()
- 使用HttpSession对象:
- Object getAttribute(String name)
- void setAttribute(String name Object value)
- void removeAttribute(String name)
- 获取HttpSession对象
-
原理:
session的实现时依赖于cookie的。
第一次发送请求,服务器会创建Session对象,并设置一个唯一的ID属性,并在相应时将该Session对象的的ID 存入响应头:set-cookie : JSESSIONID= id属性。
当客户端发送第二次请求时,cookie中就会有对应的Session id , web服务器读取到头信息后,就会将两次会话中使用的Session对象指向同一个session对象。
-
注意:
-
客户端关闭后,再次开启客户端获取的Sesion是同一个吗?
- 默认情况下不是,因为客户端关闭,cookie会被清空
- 如果需要相同,可以通过设置cookie
@WebServlet("/session1") public class SessionDemo extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取session对象 HttpSession session = req.getSession(); //System.out.println(session);//没有设置cookie存活时间前,session不是同一个 //设置cookie存活时长 Cookie cookie = new Cookie("JSESSIONID", session.getId()); cookie.setMaxAge(60 * 60); resp.addCookie(cookie); System.out.println(session); } }
- 服务器重新启动后,两个会话的Sesion是同一个吗?
-
因为Session 对象会被清空,所以很难相同。但是我们不能因为重启服务器而丢失Session数据
- 解决:Session的钝化 和 活化
- 钝化:就是将Seession对象序列化到磁盘上
- 活化:在服务器启动后,将session文件反序列化成Session对象即可。
- **注意:**Tomcat可以自动完成Session的活化和钝化,但是Idea无法演示出效果,因为idea重启服务器会先将work目录删除,再重新创建。而钝化的session文件就是在work目录中
- Session的什么时候销毁
- 解决:Session的钝化 和 活化
-
服务器关闭
-
session对象调用invalidate():将自己杀死
-
session默认失效时间:30分钟
- 可以通过tomcat — > conf —->web.xml配置失效时间
-
-
特点:
- session 用于存储一次会话中多次请求的数据,存储在服务器端
- session可以存储任意类型,任意大小的数据
-
Session 与 cookie的区别
- session存储在服务器端,cookie存储在客户端
- session没有数据大小的限制,Cookie有
- session数据安全,cookie相对不安全
6.6 登录案例优化
- 将验证码实际内容存储到session对象中进行共享
- 将错误提示信息显示在对应标签后部
3.将验证码设置为一次性验证码
3.7 JSP指令
- **作用:**用于配置JSP页面,导入资源文件
- 格式:<%@ 指令名称 属性名1=属性值1 属性名1=属性值1 %>
- 分类:
- page:配置JSP页面
- include:页面包含。(基本不用)
- taglib:导入资源,后面使用的JSTL标签就需要使用该指令导入
3.6 page指令
-
常见属性:
-
contentType:等同于response.setContentType():设置响应体的Mime类型及编码集。并且可以设置当前JSP的编码集(高级开发工具才有的功能)
-
pageEncoding: 当前页面的编码集
-
language:jsp语言,当年想统一所有表现层语言,结果没实现,所以现在的language只有 java这个属性值。
-
buffer:缓冲区大小,因为jsp中使用输出流,需要缓冲区
-
import :导包,高级开发工具会自动导包
-
errorPage:
当前页面如果报错,会自动跳转至该属性配置的页面。
- 演示:在演示案例页面中写入
<% int i = 3 /0%>
,指定errorPage属性跳转路径,即可看到效果
- 演示:在演示案例页面中写入
-
isErrorPage:标注当前页面是否是错误页面,如果为 true, 则可以使用 Exception这个内置对象
-
3.7 taglib
我们常用于引入标签库,后面学习JSTL会用到
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- prefix : 前缀,自定义
3.8 mvc开发模式
早期还没有jsp时,都是使用servlet开发,只能使用response输出标签数据,工作量非常大。后来jsp出现后,简化了 servlet的开发,开发人员开始过度的使用jsp,导致前后端无法分离,并且代码结构混乱,阅读性非常差。为了解决这写问题 后来的java开发就借鉴了MVC开发模式,具体的规定了什么代码写什么位置,使得程序设计更加合理。
- MVC
- M - Model 模型 JavaBean
- 完成具体的业务操作:比如:查询数据库,封装对象等。
- V - View 视图层 JSP
- 展示数据
- C - Controller 控制器 Servlet
- 获取用户的输入(请求)
- 调用模型
- 将数据交给视图层展示
2.优点
- 耦合性低:将代码分为三部分,各司其职,便于维护,
- 重用性高:
3.缺点
- 使得架构变复杂,对程序员要求比较高。
因为三部分各司其职,所以JSP页面仅仅做展示,所以我们需要学习替换他的两外两个技术 EL表达式 和 JSTL标签。
4.EL表达式
4.1 概述
EL - EXpression Language 表达式语言,jsp本使支持EL表达式
4.2 作用
替换 和 简化 jsp页面中java代码的编写
4.3 语法
${ 表达式 }
演示案例:
${ 3>4}
结果:页面会直接输出运算结果
\${表达式}
结果:他会原样输出4
4.4 使用
- 运算
- 算数运算:+,- ,*,/ ,%
- 比较运算:> ,< , >= , < = , >= , == ,!=
- 逻辑运算:&& (and) , ||(or) , ! (非)
- 空运算符:empty 用于判断 字符串,集合 数组对象是否为null 并且长度是否为0
<h3>算数运算符</h3>
${1+2 }<br>
${1-2 }<br>
${1*2 }<br>
${1/2 }<br>
${1%2 }<br>
<h3>逻辑运算符</h3>
${ 3>4 && 5<6}
${ 3>4 and 5<6}
- 获取值
- EL表达式只能从域对象中获取值
- 语法:${域名称. 键名} 从指定域中获取指定键的值
- 域名称:
- pageScope —>pageContext
- requestScope —> requestScope
- sessionScope —>session
- applicationScope —>application
- 举例:取出request域中的 name属性值:${request.name}
- 域名称:
演示案例1:
<%
request.setAttribute("name","刘德华");
%>
${requestScope.name}
${requestScope.age} 读不出数据也不会显示null,而是显示空格
演示案例2:
<%
request.setAttribute("name","刘德华");
session.setAttribute("name","周杰伦")
%>
${name}
语法2:${ 键名} :默认会从最小的域以此向上寻找
4.5 获取对象 和 集合
- user类
package cn.itcast.domain;
import java.text.SimpleDateFormat;
import java.util.Date;
public class User {
private String name;
private int age;
private Date birthday;
public User(String name, int age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
public User() {
}
/**
* 逻辑视图
* @return
*/
public String getBirStr(){
if(birthday != null){
//1.格式化日期对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//2.返回字符串即可
return sdf.format(birthday);
}else{
return "";
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
演示案例:
<html>
<head>
<title>el获取数据</title>
</head>
<body>
<%
User user = new User();
user.setName("张三");
user.setAge(23);
user.setBirthday(new Date());
request.setAttribute("u",user);
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add(user);
request.setAttribute("list",list);
Map map = new HashMap();
map.put("sname","李四");
map.put("gender","男");
map.put("user",user);
request.setAttribute("map",map);
%>
<h3>el获取对象中的值</h3>
${requestScope.u}<br> 这里打印的是对象的字符串表示形式
<%--
* 通过的是对象的属性来获取
* setter或getter方法,去掉set或get,在将剩余部分,首字母变为小写。
* setName --> Name --> name
--%>
${requestScope.u.name}<br>
${u.age}<br>
${u.birthday}<br>
${u.birthday.month}<br>//调用的Date类中的getMonth方法
//如果我们想获取到格式化后的日期,我们可以去user类中提供一个方法getBirStr()(下面定义)
${u.birStr}<br>
<h3>el获取List值</h3>
${list}<br>
${list[0]}<br>
${list[1]}<br>
${list[10]}<br>//越界 不会报错,显示空
${list[2].name}
<h3>el获取Map值</h3>
${map.gender}<br>
${map["gender"]}<br>
${map.user.name}
</body>
</html>
4.6 隐式对象
**概述:**el表达式中直接可以使用的对象,
只需要知道通过pageContext对象可以获取其他8个jsp内置对象
常用的是获取request对象,再获取项目的虚拟目录
${pageContext.request}<br><h4>在jsp页面动态获取虚拟目录</h4>${pageContext.request.contextPath}Copy
5. JSTL 标签
5.1 概述:
JavaServer Pages Tag Library JSP标准标签库 ,用于简化和替换jsp页面上的java代码
5.2 使用
- 导入jstl相关jar包
- 引入标签库:taglib指令: <%@ taglib %>
- 使用标签
5.3 if
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>if标签</title>
</head>
<body>
<%--
c:if标签
1. 属性:
* test 必须属性,接受boolean表达式
* 如果表达式为true,则显示if标签体内容,如果为false,则不显示标签体内容
* 一般情况下,test属性值会结合el表达式一起使用
2. 注意:c:if标签没有else情况,想要else情况,则可以在定义一个c:if标签
--%>
<c:if test="true">
<h1>我是真...</h1>
</c:if>
<br>
<%
//判断request域中的一个list集合是否为空,如果不为null则显示遍历集合
List list = new ArrayList();
list.add("aaaa");
request.setAttribute("list",list);
//判断number的奇偶性
request.setAttribute("number",4);
%>
<c:if test="${not empty list}">
遍历集合...
</c:if>
<br>
<c:if test="${number % 2 != 0}">
${number}为奇数
</c:if>
<c:if test="${number % 2 == 0}">
${number}为偶数
</c:if>
</body>
</html>
17.4 choose
<html>
<head>
<title>choose标签</title>
</head>
<body>
<%--
完成数字编号对应星期几案例
1.域中存储一数字
2.使用choose标签取出数字 相当于switch声明
3.使用when标签做数字判断 相当于case
4.otherwise标签做其他情况的声明 相当于default
--%>
<%
request.setAttribute("number",51);
%>
<c:choose>
<c:when test="${number == 1}">星期一</c:when>
<c:when test="${number == 2}">星期二</c:when>
<c:when test="${number == 3}">星期三</c:when>
<c:when test="${number == 4}">星期四</c:when>
<c:when test="${number == 5}">星期五</c:when>
<c:when test="${number == 6}">星期六</c:when>
<c:when test="${number == 7}">星期天</c:when>
<c:otherwise>数字输入有误</c:otherwise>
</c:choose>
</body>
</html>
17.5 foreach
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>foreach标签</title>
</head>
<body>
<%--
foreach:相当于java代码的for语句
1. 完成重复的操作
for(int i = 0; i < 10; i ++){
}
* 属性:
begin:开始值(包含)
end:结束值(包含)
var:临时变量 - 相当于i
step:步长,每次改变量
varStatus:循环状态对象,在普通for循环中 与 var 相同
index:容器中元素的索引,从0开始
count:循环次数,从1开始
2. 遍历容器
List<User> list;
for(User user : list){
}
* 属性:
items:容器对象-list 集合
var:容器中元素的临时变量 - 遍历操作中存储集合元素的临时变量
varStatus:循环状态对象- 循环第几次
index:容器中元素的索引,从0开始
count:循环次数,从1开始
--%>
//打印1-10的基数
<c:forEach begin="1" end="10" var="i" step="2" varStatus="s">
${i} <h3>${s.index}<h3> <h4> ${s.count} </h4><br>
</c:forEach>
<hr>
<%
List list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
request.setAttribute("list",list);
%>
//遍历集合
<c:forEach items="${list}" var="str" varStatus="s">
${s.index} ${s.count} ${str}<br>
</c:forEach>
</body>
</html>
练习:
<html>
<head>
<title>test</title>
</head>
<body>
<%
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.birStr}</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.birStr}</td>
</tr>
</c:if>
</c:forEach>
</table>
</body>
</html>
5. 过滤器
5.1 概述
1. 概述:当访问服务器资源时,过滤器可以将请求拦截下来,进行一些特殊的功能
2. 作用:一般用于完成通用的操作,比如登录操作,统一编码处理,过滤敏感字符
5.2 快速入门
步骤:
- 定义一个类,实现接口Fileter
- 复写方法
- 配置拦截路径。
演示案例
创建一个类,实现Filter接口,启动服务器,如果没有放行代码,则jsp中内容将不会给展示。
/**
* @author lp
* @version 1.0
*/
@WebFilter("/*")//访问所有资源都会被执行
public class FilterDemo1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器被执行。。。。");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
5.3 执行流程
通过代码来演示Filter的执行流程:
新建一个过滤器
@WebFilter("/*")//访问所有资源都会被执行
public class FilterDemo2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器被执行。。。。");
//放行
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("过滤器又被执行了。。。");
}
@Override
public void destroy() {
}
}
再index.jsp中添加一条输出语句
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
System.out.println("JSP被执行");
%>
</body>
</html>
执行结果:
为什么会这样呢? 因为过滤器是对访问数据和响应数据进行处理的,所以访问前,过滤会执行一次,处理request中的对象,jsp页面执行完毕后,过滤器又会对response中的数据进行处理。
有一点需要注意的是,过滤器再次被执行就从 放行语句后开始执行
5.4 过滤器配置:(只讲注解方式)
-
拦截路径配置:
1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行 2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行 3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行 4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
-
拦截方式配置:资源被访问的方式:直接访问,转发等
- 注解配置:
- 设置dispatcherTypes属性
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源 :jsp 中配置
- ASYNC:异步访问资源
- 设置dispatcherTypes属性
- 注解配置:
@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.REQUEST)//配置一种方式
@WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})//配置多种访问方式被拦截
5.5 过滤器链
这里我们只需要了解执行顺序即可
- 执行顺序:如果有两个过滤器:过滤器1和过滤器2
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
- 过滤器先后顺序:按照类名字符串比较顺序。xml配置按照配置先后。