JavaWeb入门到入土_Day03

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上限知识点:

  1. 一个cookie只能保存一个信息
  2. 一个web站点可以给浏览器发送多个cookie,每个web站点最多存放20个cookie( 不同的浏览器会有所不同)
  3. cookie大小有限制4kb
  4. 浏览器上限是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由服务器创建
    cookie和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原理
此外:在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>");
%>

JSP脚本片段

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>

JSP报错界面
定制错误界面

<%@ 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头部尾部测试
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>

分析源码
jsp标签源码
对比

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

使用步骤

  1. 引入对应的taglib;
  2. 使用其中的方法
  3. 在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表

idnameageaddress
00122深圳
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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值