JavaWeb
7. Cookie、Session
7.1 会话
会话:用户打开一个浏览器,点击了很多超链接,访问了多个web资源,最后关闭浏览器,这个过程称之为会话;
有状态会话:用户登陆一个网站,下次登陆同一个网站时,网站可以识别出用户曾经登陆过,这个过程称之为有状态会话。
HTTP是一个无状态的协议。无状态指本次请求和上一次请求没有任何关系,互不认识。这种无状态的好处是快速;坏处是假如我们想要把www.zhihu.com/login.html和www.zhihu.com/index.html关联起来,就必须使用某些手段和工具。
7.2 会话保持的两种技术
cookie
- 客户端技术(响应,请求)
session
- 服务端技术,利用这个技术,我们可以保存用户的会话信息,把信息或者数据放在session中。
常见场景:网站登录之后,客户端下次不用再登录了,第二次访问直接就上去了。
7.3 Cookie
- 服务器从客户端发送的请求中拿到cookie信息
- 服务器响应给客户端新的cookie
Cookie[] cookies = req.getCookies(); // 获取cookie数组
cookie.getName(); // 获取cookie中的key
cookie.getValue(); // 获取cookie中的value
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + ""); // 新建一个cookie
cookie.setMaxAge(24 * 60 * 60); // 设置cookie的有效期
resp.addCookie(cookie); // 响应给客户端一个cookie
cookie:一般会保存在本地的用户目录下/AppData下
服务器、网站cookie上限知识点:
- 一个cookie只能保存一个信息
- 一个web站点可以给浏览器发送多个cookie,每个web站点最多存放20个cookie( 不同的浏览器会有所不同)
- cookie大小有限制4kb
- 浏览器上限是300个cookie
删除cookie
- 不设置有效期,关闭浏览器后会自动失效;
- 设置有效期时间为0
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wang</groupId>
<artifactId>CookieDemo01</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</project>
web.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"
metadata-complete="true">
<servlet>
<servlet-name>c1</servlet-name>
<servlet-class>com.wang.servlet.CookieDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>c1</servlet-name>
<url-pattern>/c1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>c2</servlet-name>
<servlet-class>com.wang.servlet.CookieDemo02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>c2</servlet-name>
<url-pattern>/c2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>c3</servlet-name>
<servlet-class>com.wang.servlet.CookieDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>c3</servlet-name>
<url-pattern>/c3</url-pattern>
</servlet-mapping>
</web-app>
CookieDemo01.java
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.text.SimpleDateFormat;
import java.util.Date;
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决请求和响应中的中文乱码
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
// cookie,服务器从客户端的请求中获取
Cookie[] cookies = req.getCookies(); // 这里返回的是数组,说明Cookie可能存在多个
if (cookies == null) {
out.print("Welcome to my web!");
} else {
out.print("The last time of access is:" );
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookie.getName().equals("lastLoginTime")) {
long lastLoginTime = Long.parseLong(cookie.getValue());
Date date = new Date(lastLoginTime);
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
out.print(sd.format(date));
}
}
}
// 添加or更新cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// 设置cookie为1天
cookie.setMaxAge(24 * 60 * 60);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
CookieDemo02.java
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.text.SimpleDateFormat;
import java.util.Date;
public class CookieDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决请求和响应中的中文乱码问题
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
// 添加or更新cookie
Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");
// 设置有效期为0
cookie.setMaxAge(0);
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
CookieDemo03.java
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.net.URLDecoder;
import java.net.URLEncoder;
public class CookieDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 解决请求和响应的中文乱码问题
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
//cookie,服务器从客户端中获取
Cookie[] cookies = req.getCookies();
if (cookies == null) {
out.print("Welcome to my web!");
} else {
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookie.getName().equals("name")) {
// 防止cookie在网络传输中出现中文乱码问题
out.print(URLDecoder.decode(cookie.getValue(), "UTF-8"));
}
}
}
// 添加or更新cookie
Cookie cookie = new Cookie("name", URLEncoder.encode("王", "UTF-8"));
resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
7.4 Session(重点)
7.4.1 What
- 服务器会给每一个用户(浏览器)创建一个session对象;
- 一个session独占一个浏览器,只要浏览器没有关闭,session就一直存在;
- 用户登录之后,整个网站都可以访问
7.4.2 重要方法
方法 | 功能 |
---|---|
public Object getAttribute(String name); | 返回session对象中与指定名称绑定的对象, 如果不存在则返回null |
public Enumeration getAttributeNames(); | 返回session对象中所有的对象名称 |
public long getCreationTime(); | 返回session对象被创建的时间(以毫秒为单位) 从1970年1月1号凌晨开始算起 |
public String getId(); | 返回session对象的ID |
public long getLastAccessedTime(); | 返回客户端最后访问的时间,以毫秒为单位, 从1970年1月1号凌晨开始算起 |
public int getMaxInactiveInterval(); | 返回最大时间间隔,以秒为单位, servlet 容器将会在这段时间内保持会话打开 |
public void invalidate(); | 将session无效化,解绑任何与该session绑定的对象 |
public boolean isNew(); | 返回是否为一个新的客户端, 或者客户端是否拒绝加入session |
public void removeAttribute(String name); | 移除session中指定名称的对象 |
public void setAttribute(String name, Object value); | 使用指定的名称和值来产生一个对象并绑定到session中 |
public void setMaxInactiveInterval(int interval); | 用来指定时间,以秒为单位, servlet容器将会在这段时间内保持会话有效 |
7.4.3 Session应用实例
Person.java
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
SessionDemo01.java(在session中存入对象kv值)
import com.wang.pojo.Person;
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;
public class SessionDemo01 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");
//获取session
HttpSession session = req.getSession();
//给session存值
session.setAttribute("person", new Person("wang", 22));
//获取session的id
String sessionId = session.getId();
if (session.isNew()) {
resp.getWriter().write("session创建成功,ID: " + sessionId );
} else {
resp.getWriter().write("session已经在服务器中存在了,ID: " + sessionId );
}
// session创建的时候做了什么
// Cookie cookie = new Cookie("JSESSIONID", id);
// resp.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
SessionDemo02.java(获取session与key对应的value值并输出)
import com.wang.pojo.Person;
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;
public class SessionDemo02 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");
//获取session
HttpSession session = req.getSession();
//获取session与key对应的value值并输出
Person person = (Person) session.getAttribute("person");
System.out.println(person.toString());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
SessionDemo03.java(清空session)
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;
public class SessionDemo03 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");
//获取session
HttpSession session = req.getSession();
//手动注销session
session.invalidate();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.xml
<servlet>
<servlet-name>s1</servlet-name>
<servlet-class>com.wang.servlet.SessionDemo01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>s1</servlet-name>
<url-pattern>/s1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>s2</servlet-name>
<servlet-class>com.wang.servlet.SessionDemo02</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>s2</servlet-name>
<url-pattern>/s2</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>s3</servlet-name>
<servlet-class>com.wang.servlet.SessionDemo03</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>s3</servlet-name>
<url-pattern>/s3</url-pattern>
</servlet-mapping>
测试:先输入URL:localhost:8080/s3 清空session(启动浏览器时session已存在),再输入localhost:8080/s2 获取session中与key对应的value值,会报错(内部服务器错误500)
7.4.4 拓展
web.xml可以设置session自动失效时间
<session-config>
<!--设置session自动失效时间,单位分钟-->
<session-timeout>1</session-timeout>
</session-config>
session和cookie的区别
- cookie是把用户的数据写给浏览器,浏览器保存(可以保存多个);
- session是把用户的数据写到用户独占的session中,服务器端保存(保存重要的信息,避免服务器的资源浪费);
- session由服务器创建
8. JSP
8.1 What
JSP(全称JavaServerPages)是由Sun Microsystems公司主导创建的一种动态网页技术标准。JSP部署于网络服务器上,可以响应客户端发送的请求,并根据请求内容动态地生成HTML、XML或其他格式文档的Web网页,然后返回给请求者。JSP技术以Java语言作为脚本语言,为用户的HTTP请求提供服务,并能与服务器上的其它Java程序共同处理复杂的业务需求。
JSP将Java代码和特定变动内容嵌入到静态的页面中,实现以静态页面为模板,动态生成其中的部分内容。JSP引入了被称为“JSP动作”的XML标签,用来调用内建功能。另外,可以创建JSP标签库,然后像使用标准HTML或XML标签一样使用它们(JSP写法类似于HTML)。标签库能增强功能和服务器性能,而且不受跨平台问题的限制。JSP文件在运行时会被其编译器转换成更原始的Servlet代码;JSP编译器可以把JSP文件编译成用Java代码写的Servlet,然后再由Java编译器来编译成能快速执行的二进制机器码,也可以直接编译成二进制码。
特点:
- 能以模板化的方式简单、高效地添加动态网页内容;
- 可利用JavaBean和标签库技术复用常用的功能代码(设计好的组件容易实现重复利用,减少重复劳动)。标签库不仅带有通用的内置标签JSTL,而且支持可扩展功能的自定义标签;
- 有良好的工具支持;
- 继承了Java语言的相对易用性;
- 继承了Java的跨平台优势,实现“一次编写,处处运行”。因为支持Java及其相关技术的开发平台多,网站开发人员可以选择在最适合自己的系统平台上进行JSP开发;不同环境下开发的JSP项目,在所有客户端上都能顺利访问;
- 页面中的动(控制变动内容的部分)/静(内容不需变动的部分)区域以分散但又有序的形式组合在一起,能使人更直观地看出页面代码的整体结构,也使得设计页面效果和程序逻辑这两部分工作容易分离(外观视图与逻辑分离)。从而方便分配人员并发挥各自长处,实现高效地分工合作;
- 可与其它企业级Java技术相互配合,即 JSP可以只专门负责页面中的数据呈现,实现分层开发。
8.2 JSP原理
代码层面:没有什么特殊之处;
Tomcat层面:Tomcat文件夹下会出现一个work目录,里面存放的是JSP程序被翻译后生成的Java程序(Servlet类)
因此我们可以得出结论,浏览器向服务器发送请求,不管访问什么资源,其实都是在访问servlet;也即JSP最终都会被转换成一个Java类,本质上也就是一个Servlei类.
Tomcat文件夹中的Java程序
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {}
HttpJspBase类的继承关系
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {}
源码分析
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
// 初始化
public void _jspInit() {}
// 销毁
public void _jspDestroy() {}
// JSPservice
public void _jspService(final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
// 1.判断请求方式
// ...
// 2.内置一些对象
final javax.servlet.jsp.PageContext pageContext; // 页面上下文
javax.servlet.http.HttpSession session = null; // session
final javax.servlet.ServletContext application; // applicationContext
final javax.servlet.ServletConfig config; // config
javax.servlet.jsp.JspWriter out = null; // out
final java.lang.Object page = this; // page:当前页
// ...
// 3.输出页面前增加的代码
response.setContentType("text/html"); // 设置响应页面类型
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;
// 4.以上对象我们可以在JSP中直接使用。
}
}
此外:在JSP页面中,Java代码会原封不动的输出(<%Java代码%>),而HTML代码则会被转化为以下方式输出至前端:
out.write(" <title>Title</title>\r\n");
8.3 JSP基础语法和指令
任何语言都有自己的语法,JSP作为Java技术的一种应用,在拥有自己扩充的语法的同时,也支持Java所有的语法。
JSP所需依赖pom.xml
<dependencies>
<!--servlet依赖-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--jsp依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!--jstl依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
8.3.1 JSP表达式
<%= 变量或者表达式%>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%--JSP表达式:用来将程序的结果输出到客户端--%>
<%= new Date()%>
</body>
</html>
8.3.2 JSP脚本片段
<% 脚本片段 %>
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
out.println("<h1>sum=" + sum + "</h1>");
%>
8.3.3 脚本片段的再实现
<%
int i = 5;
out.print("i = " + i);
%>
<p>这是一个JSP文档</p>
<%
i += 5;
out.print("i = " + i);
%>
<hr>
<%--在代码中嵌入HTML元素--%>
<%
for (int j = 0; j < 5; j++) {
%>
<h2>hello<%=j%></h2>
<%
}
%>
8.3.4 JSP声明
<%! JSP声明 %>
<%!
static {
System.out.println("servlet load...");
}
private String globalVar = "wang";
public void wang() {
System.out.println("进入了wang方法!");
}
%>
<%wang();%>
JSP声明会被编译到JSP生成Java代码的类中!其他的(表达式、脚本片段等…)则会被生成到_jspService方法中!
8.3.5 JSP注释
<!--这是HTML的注释-->
<%--这是JSP的注释--%>
JSP的注释不会在客户端中显示,而HTML的注释则会在客户端中显示。
8.4 JSP指令
<%@ page args... %> 配置JSP的一些参数
<%@ include file=""%> 设置一些网站多页面共用的头步和尾部
8.4.1 JSP报错界面实例
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int i = 1/0;
%>
</body>
</html>
定制错误界面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--定制错误页面--%>
<%@ page errorPage="error/500.jsp" %>
<%
int i = 1/0;
%>
</body>
</html>
500.jsp(JSP文件在web目录下error文件夹中存放;image文件在web目录下img文件夹中存放)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>error</title>
</head>
<body>
<img src="../img/error_500.jpg">
</body>
</html>
除了在JSP中配置错误界面,还可以在web.xml中配置错误界面
<error-page>
<error-code>500</error-code>
<location>/error/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
400.jsp(JSP文件在web目录下error文件夹中存放;image文件在web目录下img文件夹中存放)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>error</title>
</head>
<body>
<img src="../img/error_404.jpg">
</body>
</html>
8.4.2 JSP页面头部尾部实例
footer.jsp(web/common文件夹中)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>我是Footer</h1>
header.jsp(web/common文件夹中)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>我是Header</h1>
mainPage.jsp(web文件夹中)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
%@include会将两个页面合二为一,要注意页面合并后的冲突(比如两个页面都定义了int i = 10则会报错)
--%>
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<%@include file="common/footer.jsp"%>
</body>
</html>
JSP标签
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--jsp标签
jsp:include 本质是三个页面拼接,因此不会出现上面的int i=10冲突的情况,推荐使用
--%>
<jsp:include page="common/header.jsp"/>
<h1>网页主体</h1>
<jsp:include page="common/footer.jsp"/>
</body>
</html>
分析源码
8.5 九大内置对象
- PageContext【存东西】
- Request 【存东西】
- Response
- Session【存东西】
- Application(ServletContext)【存东西】
- config(ServletConfig)
- out
- page 【基本用不到】
- exception
作用域
pageContextDemo1.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--内置对象--%>
<%
pageContext.setAttribute("name1","wang1"); // 保存的数据只在一个页面中有效
request.setAttribute("name2","wang2"); // 保存的数据只在一次请求中有效,请求转发会携带这个数据
session.setAttribute("name3","wang3"); // 保存的数据只在一次会话中有效,从打开浏览器到关闭浏览器
application.setAttribute("name4","wang4"); // 保存的数据只在服务器中有效,从打开服务器到关闭服务器
%>
<%--脚本片段中的代码会原封不动生成到xxx.jsp.java;因此<%...%>中的代码必须保证Java语法的正确性--%>
<%
// 从pageContext取出,我们通过寻找的方式来获取属性
// 从底层到高层(作用域)
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5"); // 不存在
%>
<%--使用EL表达式输出 ${} --%>
<h1>取出的值为</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>
<h3><%=name5%></h3>
</body>
</html>
pageContextDemo2.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--脚本片段中的代码会原封不动生成到xxx.jsp.java;因此<%...%>中的代码必须保证Java语法的正确性--%>
<%
// 从pageContext取出,我们通过寻找的方式来获取属性
// 从底层到高层(作用域):page->request->session->application
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5"); // 不存在
%>
<%--使用EL表达式输出 ${} --%>
<h1>取出的值为</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
<h3>${name5}</h3>
<h3><%=name5%></h3>
</body>
</html>
测试访问(先请求pageContextDemo1.jsp然后再请求pageContextDemo2.jsp,否则都取不到值)
结果只能访问到name3和name4,name1和name2超出作用域(name2在页面实现转发后可以在转发的页面中访问到),name5不存在。
pageContextDemo3.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
public void setAttribute (String name, Object attribute, int scope){
switch (scope) {
case PAGE_SCOPE:
mPage.put (name, attribute);
break;
case REQUEST_SCOPE:
mRequest.put (name, attribute);
break;
case SESSION_SCOPE:
mSession.put (name, attribute);
break;
case APPLICATION_SCOPE:
mApp.put (name, attribute);
break;
default:
throw new IllegalArgumentException ("Bad scope " + scope);
}
}
--%>
<%--内置对象--%>
<%
pageContext.setAttribute("name1","wang1", PageContext.REQUEST_SCOPE);
//等价于 request.setAttribute("name1","wang1");
%>
</body>
</html>
pageContextDemo4.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
pageContext.forward("/index.jsp");
// request.getRequestDispatcher("/index.jsp").forward(request, response);
%>
</body>
</html>
作用域
request:客户端向服务器发送请求,产生的数据,用户看完就没用了,比如:新闻
session:客户端向服务器发送请求,产生的数据,用户用完一会还有用,比如:购物车
application:客户端向服务器发送请求,产生的数据,一个用户用完了其他用户还可能使用,比如聊天数据
8.6 JSP标签、JSTL标签、EL表达式
依赖
<!--jstl依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表达式(Expression Language)
- 获取数据
- 执行运算
- 获取web开发的常用对象
调用Java方法
JSP标签
jsptag.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>tag1</h1>
<%--<jsp:include>用于拼接页面--%>
<%-- http://localhost:8080/jsptag.jsp?name=wang&age=18 --%>
<jsp:forward page="/jsptag2.jsp">
<jsp:param name="name" value="wang"/>
<jsp:param name="age" value="18"/>
</jsp:forward>
</body>
</html>
jsptag2.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>tag2</h1>
姓名:<%=request.getParameter("name")%>
年龄:<%=request.getParameter("age")%>
</body>
</html>
JSTL表达式
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义了许多标签供我们使用,标签的功能和Java代码一样!
- 核心标签库(要求掌握)
- 格式化标签
- SQL标签
- XML标签
引用核心标签库的语法如下:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
标签 | 描述 |
---|---|
<c:out> | 用于在JSP中显示数据,就像<%= … > |
<c:set> | 用于保存数据 |
<c:remove> | 用于删除数据 |
<c:if> | 与我们在一般程序中用的if一样 |
<c:choose> | 本身只当做<c:when>和<c:otherwise>的父标签 |
<c:when> | <c:choose>的子标签,用来判断条件是否成立 |
<c:otherwise> | <c:choose>的子标签,接在<c:when>标签后,当<c:when>标签判断为false时被执行 |
<c:forEach> | 基础迭代标签,接受多种集合类型 |
<c:url> | 使用可选的查询参数来创造一个URL |
使用步骤
- 引入对应的taglib;
- 使用其中的方法
- 在Tomcat中也需要引入JSTL的包,否则会报错:JSTL解析错误
coreIf.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--引入JSTL核心标签库,我们才能使用JSTL标签--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h4>if测试</h4>
<form action="coreIf.jsp" method="get">
<%--EL表达式${param.参数名}获取表单中的数据--%>
<input type="text" name="username" value="${param.username}">
<input type="submit" value="登录">
</form>
<%--判断如果提交的用户名是admin,则登录成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin">
<c:out value="管理员!"></c:out>
</c:if>
<c:out value="${isAdmin}"></c:out>
</body>
</html>
coreWhen.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:set var="score" value="100"/>
<c:choose>
<c:when test="${score>=90}">Your grade is A!</c:when>
<c:when test="${score>=80}">Your grade is B!</c:when>
<c:when test="${score>=60}">Your grade is C!</c:when>
<c:otherwise>You out!</c:otherwise>
</c:choose>
</body>
</html>
coreForeach.jsp
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
List<String> personList = new ArrayList<>();
personList.add(0, "张三");
personList.add(1, "李四");
personList.add(2, "王五");
personList.add(3, "赵六");
request.setAttribute("personList", personList);
%>
<%--
var 每一次遍历出来的变量
item 要遍历的对象
begin 开始下标
end 结束下标
step 步长
--%>
<c:forEach var="person" items="${personList}">
<c:out value="${person}"/><br/>
</c:forEach>
<hr/>
<c:forEach var="person" items="${personList}" begin="1" end="3" step="2">
<c:out value="${person}"/><br/>
</c:forEach>
</body>
</html>
9. JavaBean(实体类)
javaBean特定的写法:
- 必须要有一个无参构造
- 属性必须私有化
- 必须有对应的get/set方法
一般用来和数据库字段做映射
ORM:对象关系映射
表 ——> 类
字段 ——> 属性
行记录 ——> 对象
person表
id | name | age | address |
---|---|---|---|
001 | 王 | 22 | 深圳 |
class Person{
private int id;
private String name;
private int age;
private String address;
// ...构造方法以及Get、Set方法
}
javabean.jsp
<%@ page import="com.wang.pojo.Person" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
//Person person= new Person();
//person.setAddress("深圳");
//person.setAge(22);
//person.setId(1);
//person.setName("wang");
%>
<jsp:useBean id="person" class="com.wang.pojo.Person" scope="page"/>
<jsp:setProperty name="person" property="address" value="深圳"/>
<jsp:setProperty name="person" property="age" value="22"/>
<jsp:setProperty name="person" property="id" value="1"/>
<jsp:setProperty name="person" property="name" value="wang"/>
<%-- <%=student.getId()%> --%>
id:<jsp:getProperty name="student" property="id"/>
name:<jsp:getProperty name="student" property="name"/>
age:<jsp:getProperty name="student" property="age"/>
address:<jsp:getProperty name="student" property="address"/>
</body>
</html>