前言

出于提升HTTP传输效率考虑,HTTP协议是无状态的。

HTTP不会记录每次请求的状态,这就造成了同一个会话中的2个请求之间相互独立,彼此之间没有任何联系。

本文将基于servlet的session机制结合JSP,实现1个用户登录的Web应用,深入理解一下Java Web应用的核心架构。

 

一、会话保持技术

在Web应用中的1次会话中,包含多次HTTP请求和响应。

会话技术是针对HTTP请求无状态的特性,在一次会话中(多次HTTP请求和响应之间)保存数据 。

Cookie和Session是2种HTTP请求会话保持技术,其中Session机制基于Cookie机制。

 

二、Cookie

Cookie信息保存在客户端(浏览器),信息大小限制在4KB,其机制如下。

  • 客户端请求服务器,服务器通过HTTP响应头中set-Cooke键告诉客户端保存Cookie。
  • 浏览器接收到服务器回写Cookie要求,通过键值对的形式,在本地设置Cookie,键重复就覆盖。
  • 每次浏览器请求服务器之前都会自动携带上浏览器本地的Cookie信息,除非使用Ajax向服务器发送请求。
  • 服务器可以通过客户端携带的Cookie校验当前客户端并保存HTTP请求状态。

1.添加cookie信息

//2.创建明文Cookie信息
            Cookie cookie = new Cookie("product1", product);
            //2.1创建加密Cookie信息
            Cookie encodecookie = new Cookie("product2", URLEncoder.encode("爱我中华","utf-8"));
            //3.将Cookie返回给浏览器
            response.addCookie(cookie);
            response.addCookie(encodecookie);

 

2.获取cookie信息

        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                //获取明文cookie
                if ("product1".equals(cookie.getName())) {
                    System.out.println(cookie.getValue());
                }
                //获取加密cookie
                if ("product2".equals(cookie.getName())) {
                    System.out.println(URLDecoder.decode(cookie.getValue(), "utf-8"));
                }
            }
        }

 

3.设置cookie有效期

cookie默认实效时间是浏览器关闭之后,也可以指定cookie的实效时间,时间单位为秒。

             //2.创建明文Cookie信息
            Cookie cookie = new Cookie("product1", product);
            //设置明文cookie的失效时间为5分钟之后
            cookie.setMaxAge(300);
            //2.1创建加密Cookie信息
            Cookie encodecookie = new Cookie("product2", URLEncoder.encode("爱我中华","utf-8"));
            //设置密文cookie的失效时间为3分钟之后
            cookie.setMaxAge(180);

 

三、Session

Session基于Cookie,保存在服务器端,Session可以在一次会话的多次请求之间共享数据;

Sessione有以下特点:

  • Session存储数据在服务器
  • Session存储类型任意(Object)
  • Session存储大小和数量没有限制(相对于内存)
  • Session存储相对安全

 Session机制如下:

  • 1. 浏览器向服务器发送一个添加购物车请求
  • 2. 服务请创建一个Session
  • 3. 通过程序向Session中添加商品信息
  • 4. 服务器通过response将session的唯一标识JSESSIONID写回到浏览器的Cookie中(通过Set-Cookie响应头)
  • 5. 当浏览器发送查询请求的时候,会将cookie中的JSESSIONID信息携带到服务器中(通过Cookie请求头)
  • 6. 服务器接收到请求之后,通过session的唯一标识定位到session
  • 7. 我们就就可以通过程序从session获取信息了

 

1. 设置session信息

void setAttribute(String name,Object value)

        //2.获取session对象,并将session信息保存到session对象
        HttpSession session = request.getSession();
        session.setAttribute("product", product);

 

2. 获取session信息

Object getAttribute(String name)

        HttpSession session = request.getSession();
        String product =(String) session.getAttribute("product");

 

3. 删除session信息

void removeAttribute(String name)

session.removeAttribute("product");

 

四、JSP技术

TCP协议是工作在传输层的数据传输管道,HTTP协议工作在应用程, 通过传输管道在浏览器和服务器之间传输字符串信息。

在Java Web技术中我们可以以下技术构建1个Web应用。

  • Tomcat接收和响应浏览器的请求和响应, 通过路由锁定1个Servlet并执行。
  • Servlet根据户端请求信息,操作数据库,获取数据,封装到域对象中,转发(forward)到1个.jsp页面。(动态数据准备)
  • JSP把获取到域对象中封装好的动态数据,渲染到HTML,完成动态数据和静态数据的整合。                (动态数据渲染到HTML)
  • Tomcat把整合好的动态数据+HTML静态数据,一同响应给客户端浏览器。  

JSP(Java Server Pages)是SUN公司在Servlet的基础上推出的一种技术,它将Java代码和HTML语句混合在同1个.jsp文件中编写。

1个JSP页面由以下2部分构成

  • HTML语句 (输出静态部分)
  • Java代码   (输出动态部分) 

 

1.JSP入门案例

<%@ page import="java.util.Date" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSP案例</title>
</head>
<body>
<%--静态部分--%>
欢迎访问本网站,当前时间为
<%--动态部分--%>
<%
    Date date = new Date();
    String formatDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    out.write(formatDate);
%>
</body>
</html>
JSP入门案例

 

2.JSP执行流程

JSP本质上就是也是个Servlet,当我们通过浏览器访问1个js页面或者通过1个servlet转发(forward)到1个jsp页面时,Tomcat会经过以下流程,把jsp页面转换成1个Servlet

Tomcat-------》Web.xml-------》.jsp页面--------》Java代码Servle-------》.Class文件-------》在JVM中运行.Class文件。

详细流程如下:

  • 客户端发出请求
  • web容器将jsp转化为servlet代码(.java)
  • web容器将转化为servlet代码编译(.class)
  • web容器加载编译后的代码并执行
  • 将执行结果响应给客户端

 

3.JSP的EL表达式

JSP中的EL(Expression Language)表达式语言,主要用来简化jsp中对java代码的操作,帮我们从内置的域对象中获取数据在前端显示出来。

语法:${表达式}

 

3.1.域对象

上一篇文章得知Tomcat都会创建request对象和session对象,借助request和session对象进行数据保存;

在jJSP中我们可以使用EL表达式,从这些对象中获取数据 ,由于数据作用的范围(域)不同,在jsp中称这些封装了servlet数据的对象,为内置域对象。

内置域对象分别如下

  • page:     当前页面有效

  • request: 当前请求有效

  • session: 当前会话有效

  • application:当前应用有效

EL表达式获取数据时,会依次从这4个域中寻找,直到找到为止。

而这四个域对象的作用范围如下图所示

 

3.1.获取内置域对象中封装的对象数据

从对象获取数据使用点(对象.属性);

获取精准域中数据

  • ${requestScope.键名} 从HttpServletRequest域中获取
  • ${sessionScope.键名} 从HttpSession域中获取

简化写法

  • ${键名} 按照上面的域范围从小到大依次从四个域中进行查找;如果从某一个域中找到了,立即返回;如果四个域中都没有,则返回空
<h3>获取域对象中存储的对象</h3>
user对象:${user}<br>
user对象name:${user.name}<br>
user对象age:${user.age}<br>

 

3.2.获取内置域对象中其他数据类型的数据

<h3>获取域对象中存储的List</h3>
List的集合:${userList}<br>
List的集合第1个元素:${userList[0]}<br>
List的集合第2个元素:${userList[1]}<br>

 

4.JSP标准标签库

Java server pages standarded tag library,即JSP标准标签库

JSP标准标签库可以在jsp中实现Java的流程控制(判断+ 循环遍历)。

<%--使用jstl,必须加上这行--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 

4.1导入jar包

 

 

 

 

4.2.if标签

if标签用于单分支条件判断,相当于Java中的`if(条件){}`的用法,它的常见用法如下:

<c:if test="条件">
条件成立的逻辑
</c:if>


注意: 它只有if的功能,没有else的功能,如果需要else,需要自己取反操作

 

4.3.forEach标签

forEach用于循环遍历,相当于java中的for关键字,它的常见属性如下:
begin:设置循环的开始
end:设置循环的结束
var:声明循环过程中的临时变量名字
step:设置步长——间隔几次循环,执行一次循环体中的内
items:指定要循环的对象
varStatus:保存了当前循环过程中的信息(循环的开始、结束、步长、次数等)
forEach标签的主要用法有下面两种:

 

4.3.1. 增强for循环

<c:forEach items="数据集合" var="x">
${x}
</c:forEach>

 

4.3.2. 普通for循环

<c:forEach begin="1" end="10" step="1" var="x">
${x}
</c:forEach>

 

5.Servler+JSP实现用户登录案例

package com.zhanggen.servlet;
import domain.Person;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        HttpSession session = request.getSession();
        String sessionCode = (String) session.getAttribute("code");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String code = request.getParameter("code");

        if (!"zhanggen".equals(username) || !"123.com".equals(password)) {
            response.getWriter().write("用户名/密码错误");
            return;
        }
        if (!"".equals(sessionCode) && !"".equals(code) && code.equals(sessionCode)) {
            ArrayList<Person> friendsList = new ArrayList<>();
            friendsList.add(new Person("Lisa", 36, "河南.安阳"));
            friendsList.add(new Person("Cindy", 26, "内蒙古.乌兰察布"));
            friendsList.add(new Person("Vici", 22, "辽宁.沈阳"));
            friendsList.add(new Person("Andrea", 29, "河南.郑州"));
            friendsList.add(new Person("Wilsion", 36, "四川.绵阳"));
            friendsList.add(new Person("张无忌", 36, "河北.秦皇岛"));
            request.setAttribute("username", username);
            request.setAttribute("friendsList", friendsList);
            ///WEB-INF/下的资源,只能通过请求转发进行访问
            request.getRequestDispatcher("/index.jsp").forward(request, response);
            return;
        }

        response.getWriter().write("验证码错误");

    }
}
LoginServlet

----------------------------------------------

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--使用jstl,必须加上这行--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>微信</title>
</head>
<body>
<h1>欢迎${username}来到微信</h1>
<table style="border: aqua solid 2px">
    <thead>
    <tr>
        <td>编号</td>
        <td>姓名</td>
        <td>年龄</td>
        <td>地址</td>
    </tr>
    </thead>
    <tbody>
    <c:forEach items="${friendsList}" var="friend" varStatus="status">
        <c:if test="${status.count%2 ==0}">
            <tr style="color: antiquewhite">
                <td>
                        ${status.count}
                </td>
                <td>
                        ${friend.name}
                </td>
                <td>
                        ${friend.age}
                </td>
                <td>
                        ${friend.address}
                </td>
            </tr>
        </c:if>
        <c:if test="${status.count%2 !=0}">
            <tr style="color: blue">
                <td>
                        ${status.count}
                </td>
                <td>
                        ${friend.name}
                </td>
                <td>
                        ${friend.age}
                </td>
                <td>
                        ${friend.address}
                </td>
            </tr>
        </c:if>

    </c:forEach>
    </tbody>
</table>
</body>
</html>
index.jsp

 

posted on 2022-04-26 18:29  Martin8866  阅读(356)  评论(0编辑  收藏  举报