美文网首页
Java Web 基础 - JSP

Java Web 基础 - JSP

作者: 千反田爱瑠爱好者 | 来源:发表于2018-10-08 22:44 被阅读67次

JSP 即 Java Server Pages,是一种简化的 Servlet 设计,实现了在 Java 中使用 HTML 标签。JSP 作为一种动态网页技术标准 也是 Java EE 的标准,与Servlet 一样,实在服务器端执行的。

常见动态网站开发技术对比

  • JSP:Java 平台,安全性高,适合开发大型、企业级的 Web 应用程序;
  • ASP.net:.Net 平台,简单易学,但安全性和跨平台性差;
  • PHP:简单高效,成本低、开发周期短,适合中小型企业的 Web 应用开发(LAMP:Linux + Apache + MySQL + PHP)。

页面元素

指令

  • page:位于 JSP 页面顶端,一个页面可以有多个;
  • include:将外部文件嵌入当前 JSP 中,同时解析这个页面中的 JSP 语句;
  • taglib:使用标签库定义新的自定义标签,在 JSP 页面中启用定制行为。

page 指令

<%@ page 
    contentType="text/html;charset=UTF-8" 
    language="java" 
    import="java.util.*"
%>

其中 pageEncoding 是 JSP 文件本身的编码,contentType 的 charset 是指服务端发给客户端时的内容编码,contentType 更常用。

注释

JSP 中的注释有三种

  • HTML 注释(客户端/浏览器可见)
  • JSP 注释(客户端不可见)
  • JSP 脚本注释
<!-- HTML 注释 -->

<%-- JSP 注释 --%>

<%
// 单行注释
/*
    多行注释
*/
%>

脚本

在 JSP 页面中执行 Java 代码。

实例:使用脚本输出九九乘法表

<%!
    void printMultiTable(JspWriter out) throws Exception {
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i; j++)
                out.println(i + "*" + "=" + i * j + "&nbsp;&nbsp;&nbsp;&nbsp;");
            out.println("<br>");
        }
    }
%>
<% printMultiTable(out); %>

声明

在 JSP 页面中定义变量或方法

<%!
    String name = "ywh";
    Integer age = 16;
    String  getDesc(String name, Integer age) {
        return "name: " + name + ", age: " + age.toString();
    }
%>

表达式

在 JSP 页面中执行表达式,注意不能有分号。

实例:使用表达式打印九九乘法表

<%!
    String printMultiTable() {
        String s = "";
        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i; j++)
                s += i + "*" + "=" + i * j + "&nbsp;&nbsp;&nbsp;&nbsp;";
            s += "<br>";
        }
        return s;
    }
%>

<!-- 下面这个是表达式 -->
<%=printMultiTable()%>

静态内容

...

生命周期

JSP 实际上是一种 Servlet 对象;通过 tomcat/ work/ Catalina/ localhost 目录可以看到生成的 java 源代码(包含 jsp 初始化、解析执行的方法),其生命周期:

  1. 用户发出请求(如访问 index.jsp)
  2. 服务端判断用户是否首次发起请求:
    2.1 是,JSP 引擎把该 JSP 文件转换成(先执行构造方法)一个 Servlet 对象,生成字节码文件,并执行 jspInit(),访问字节码文件;
    2.2 否,直接访问字节码文件;
  3. 解析执行字节码文件,调用 jspService() 方法。

jspService():用于处理客户端请求,对于每个请求都创建一个新的线程来处理,如果多个客户端同时请求,则 JSP 引擎会创建多个线程(每个客户端对应一个);使用多线程可以大大降低对系统的资源需求,提高系统的并发量和减少响应时间。但也可能存在线程同步问题。由于该 Servlet 常驻于内存,响应速度很快。

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*"%>
<%@ page import="java.text.*" %>
<html>
<head>
    <title>JSP</title>
</head>
<body>
    <%
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String s = sdf.format(new Date());
    %>
    today: <%=s%>
</body>
</html>

内置对象

JSP 内置对象是 Web 容器创建的一组对象,不使用 new 关键字就可以使用的内置对象。

  • out
  • request
  • response
  • session
  • application
  • Page, PageContext, exception, config

out 对象

out 对象是缓冲区(内存的一块保存临时数据的区域)相关的 JspWriter 类的实例,向客户端输出内容的对象。

<body>
    <%
        out.println("<h2>静夜思</h2>");
        out.println("床前明月光<br>");
        out.println("疑是地上霜<br>");
        out.flush();
        //out.clear();           //这里会抛出异常。
        out.clearBuffer();       //这里不会抛出异常。
        out.println("举头望明月<br>");
        out.println("低头思故乡<br>");
    %>
    缓冲区大小:<%=out.getBufferSize() %>byte<br>
    缓冲区剩余大小:<%=out.getRemaining() %>byte<br>
    是否自动清空缓冲区:<%=out.isAutoFlush() %><BR>
</body>

request 对象

客户端请求信息被封装在 request 对象中,是 HttpServletRequest 类的实例。request 对象具有请求域,即完成客户端的请求之前该对象会一直有效。

<body>
    <h1>request内置对象</h1>
    <%
        request.setCharacterEncoding("utf-8");   // 无法解决URL传递中文出现的乱码问题,需要修改 Tomcat 配置文件
        request.setAttribute("password", "123456");
    
    %>
    用户名:<%=request.getParameter("username") %><br>
    爱好 :<%
        if (request.getParameterValues("favorite") != null) {
            String[] favorites = request.getParameterValues("favorite");
            for (int i = 0; i < favorites.length; i++) {
                out.println(favorites[i] + "&nbsp;&nbsp;");
            }
        }
    %> <br>
    密码:<%=request.getAttribute("password") %><br>
    请求体的MIME类型:<%=request.getContentType() %><br>
    协议类型及版本号:  <%=request.getProtocol() %><br>
    服务器主机名 :<%=request.getServerName() %><br>
    服务器端口号:<%=request.getServerPort() %><BR>
    请求文件的长度 :<%=request.getContentLength() %><BR>
    请求客户端的IP地址:<%=request.getRemoteAddr() %><BR>
    请求的真实路径:<%=request.getRealPath("request.jsp") %><br>
    请求的上下文路径:<%=request.getContextPath() %><BR>
</body>

解决 URL 传递中文乱码问题,修改 Tomcat 配置文件:

<Connector port="8888"
    ...
    URIEncoding="utf-8"
/>

response 对象

包含了响应客户请求的有关信息,是 HttpServletResponse 类的实例,但在 JSP 中很少使用。reponse 对象具有页面作用域(只对某次访问有效,其他页面的 response 对当前页面无效)。

<%@ page language="java" import="java.util.*,java.io.*" contentType="text/html; charset=utf-8" %>
<%
    response.setContentType("text/html;charset=utf-8"); //设置响应的MIMI类型

    out.println("<h1>response内置对象</h1>");
    out.println("<hr>");
    // out.flush();

    PrintWriter outer = response.getWriter();    //获得输出流对象
    outer.println("大家好,我是response对象生成的输出流outer对象");
    // response.sendRedirect("reg.jsp");    //请求重定向
    
    // 请求重定向
    // response.sendRedirect("request.jsp");
    
    // 请求转发
    request.getRequestDispatcher("request.jsp").forward(request, response);
%>
  • 请求重定向:客户端行为,response.sendRedirect(),本质上是两次请求,前一次请求对象不会保存,地址栏 URL 会改变;
  • 请求转发:服务端行为,response.getRequestDispatcher().forward(req, resp); 是一次请求,转发后请求对象会保存,地址栏的 URL 不会改变。

session 对象

在服务端存储的、不同客户端与服务端一次会话的信息(时间概念),第一次 JSP 页面被装载时自动创建 session 对象,是 HttpSession 类的实例,完成会话期管理(从打开浏览器访问服务端到关闭浏览器)。

生命周期:在 Tomcat 后台管理 http://localhost:8080/manager 中可以查看 Session 存储情况。

  • 创建:第一次访问某个 JSP 或者 Servlet 时候,服务器会为当前会话创建一个 SessionId,每次客户端向服务端发送请求时,都会将此 SessionId 携带过去,服务端会对此 SessionId 进行校验;
  • 活动:某次会话中通过超链接打开新页面属于同一次会话,只要当前会话页面没有关闭,重新打开新的窗口访问同一项目资源也是同一次会话(除非所有页面关闭再重新创建);
  • 销毁:调用session.invalidate()方法、Session 过期(超时)、服务器重启都会销毁对象。

关于 session 对象:

  • Tomcat 默认 session 超时时间为 30min;
  • 设置超时时间:在代码中设置 session.setMaxInactiveInterval(xxx); // 秒,或修改 Tomcat 配置文件 web.xml
<session-config>
    <session-timeout>10</session-timeout>
</session-config>    <!-- 单位:分 -->

page1

<body>
    <%
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date d = new Date(session.getCreationTime());
        session.setAttribute("username", "admin");
        session.setAttribute("password", "123456");
        session.setAttribute("age", 20);
    
        //设置当前session最大生成期限单位是秒
        //session.setMaxInactiveInterval(10);//10秒钟
    %>
    Session创建时间:<%=sdf.format(d)%><br>
    Session的ID编号:<%=session.getId()%><BR>
    从Session中获取用户名:<%=session.getAttribute("username") %><br>
    <a href="session_page2.jsp" target="_blank">跳转到Session_page2.jsp</a>
</body>

page2

<body>
    <hr>
    <%
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        //Date d = new Date(session.getCreationTime());
        //session.setAttribute("username", "admin"); 
    %>

    Session的ID编号:<%=session.getId()%><BR>
    从Session中获取用户名:<%=session.getAttribute("username") %><br>
    Session中保存的属性有: 
    <%
        String[] names = session.getValueNames();
        for (int i = 0; i < names.length; i++) {
            out.println(names[i] + "&nbsp;&nbsp;");
        }     
    %> 
</body>

application 对象

  • ServletContext 类的实例,实现了用户间数据共享,可存放全局变量;
  • 创建于服务器启动,终止于服务器关闭(服务器启动关闭决定 application 对象);
  • 在用户前后连接、或不同用户之间的连接中,可以对 application 对象的同一属性进行操作;
  • 任何地方对 application 对象属性的操作,都影响其他用户对此的访问。
<body>
    <%
        application.setAttribute("city", "北京");
        application.setAttribute("postcode", "10000");
        application.setAttribute("email", "lisi@126.com");
    %>
    所在城市是:<%=application.getAttribute("city") %><br>
    application中的属性有:<%
        Enumeration attributes = application.getAttributeNames();
        while (attributes.hasMoreElements()) {
            out.println(attributes.nextElement() + "&nbsp;&nbsp;");
        }
    %><br>
    JSP(SERVLET)引擎名及版本号:<%=application.getServerInfo() %><br>
</body>

page 对象

指向当前 JSP 页面本身,类似类中的 this 指针,是 java.lang.Object 类的实例。

pageContext 对象

  • 提供了对 JSP 页面内所有对象及命名空间的访问(汇集了页面中的所有功能);
  • 可以访问到本页所在的 Session,可以取本页所在的 application 的某一属性值;
  • 本类名也为pageContext
<body>
    <h1>pageContext内置对象</h1>
    <hr>
    用户名是:<%=pageContext.getSession().getAttribute("username") %><br>
    <%
        // 跳转到注册页面
        // pageContext.forward("reg.jsp");
        pageContext.include("include.jsp");
    %>
</body>

config 对象

在 Servlet 初始化时,JSP 引擎向它传递信息使用到 config 对象,此信息包括 Servlet 初始化时用到的参数(通过属性名称和属性值构成)以及服务器的基本信息(通过传递一个 ServletContext 对象),常用方法:

  • getServletContext:返回含有服务器相关信息的 ServletContext 对象;
  • getInitParameter:返回初始化参数的值;
  • getInitParameterNames:返回 Servlet 初始化所需所有参数值的枚举;
  • ...

exception 对象

页面运行异常时产生,当一个 JSP 页面要应用此对象,必须把 isErrorPage 设置为 true,否则无法通过编译,实际上是 java.lang.Throwable 的对象。

test_page

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" errorPage="exception.jsp" %>
<body>
    <%
        System.out.println(100 / 0); //抛出运行时异常,算数异常
    %>
</body>

error_page

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" isErrorPage="true" %>
...
<body>
    异常的消息是:<%=exception.getMessage()%><BR>
    异常的字符串描述:<%=exception.toString()%><br>
</body>

JSP 实现用户登录

dologin.jsp:登录逻辑处理

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
    String username = "";
    String password = "";
    request.setCharacterEncoding("utf-8");    // 防止中文乱码

    username = request.getParameter("username");
    password = request.getParameter("password");

    if ("admin".equals(username) && "admin".equals(password)) {    // 如果用户和密码都等于 admin 则登录成功,服务器转发;失败则重定向到失败页面
        session.setAttribute("loginUser", username);
        request.getRequestDispatcher("login_success.jsp").forward(request, response);
    } else {
        response.sendRedirect("login_failure.jsp");
    }
%>

login.jsp:登录请求页面

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%>

<body>
<div id="container">
    <div class="logo">
        <a href="#"><img src="assets/logo.png" alt=""/></a>
    </div>
    <div id="box">
        <form action="dologin.jsp" method="post">
            <p class="main">
                <label>用户名: </label><input name="username" value=""/>
                <label>密码: </label><input type="password" name="password" value="">
            </p>
            <p class="space">
                <input type="submit" value="登录" class="login" style="cursor: pointer;"/>
            </p>
        </form>
    </div>
</div>
</body>

login_success.jsp:登录成功转发页面

<body>
<div id="container">
    <div class="logo">
        <a href="#"><img src="assets/logo.png" alt=""/></a>
    </div>
    <div id="box">
        <%
            String loginUser = "";
            if (session.getAttribute("loginUser") != null) 
                loginUser = session.getAttribute("loginUser").toString();
        %>
        欢迎您<font color="red"><%=loginUser%>
    </font>,登录成功!
    </div>
</div>
</body>

login_failure.jsp:登录失败重定向页面

<div id="container">
    <div class="logo">
        <a href="#"><img src="assets/logo.png" alt=""/></a>
    </div>
    <div id="box">
        登录失败!请检查用户或者密码!<br>
        <a href="login.jsp">返回登录</a>
    </div>
</div>

JSP 状态管理

HTTP 协议的无状态性:浏览器发送请求给服务器,服务器响应客户端请求,但当同一浏览器再次发送请求给服务器时,服务器并不知道它就是之前那个浏览器。

保存用户状态的两大机制:

  • Cookie
  • Session

实例:JSP 中使用 Cookie 实现用户登录

dologin.jsp

<%@ page language="java" import="java.util.*,java.net.*" contentType="text/html; charset=utf-8" %>

<body>
    <%
        request.setCharacterEncoding("utf-8");
        String[] isUseCookies = request.getParameterValues("isUseCookie");
    
        if (isUseCookies != null && isUseCookies.length > 0) {      // 首先判断用户是否选择了记住登录状态
    
            String username = URLEncoder.encode(request.getParameter("username"), "utf-8");     // 把用户名和密码保存在Cookie对象里面
            String password = URLEncoder.encode(request.getParameter("password"), "utf-8");     // 使用URLEncoder解决无法在Cookie当中保存中文字符串问题
    
            Cookie usernameCookie = new Cookie("username", username);
            Cookie passwordCookie = new Cookie("password", password);
            usernameCookie.setMaxAge(864000);
            passwordCookie.setMaxAge(864000);       // 设置最大生存期限为10天
            response.addCookie(usernameCookie);
            response.addCookie(passwordCookie);
        }
        else {
            Cookie[] cookies = request.getCookies();
            if (cookies != null && cookies.length > 0) {
                for (Cookie c : cookies) {
                    if (c.getName().equals("username") || c.getName().equals("password")) {
                        c.setMaxAge(0);             // 设置Cookie失效
                        response.addCookie(c);      // 重新保存。
                    }
                }
            }
        }
    %>
    <a href="users.jsp" target="_blank">查看用户信息</a>
</body>

login.jsp

<%@ page language="java" import="java.util.*,java.net.*" contentType="text/html; charset=utf-8" %>

<body>
    <%
        request.setCharacterEncoding("utf-8");
        String username = "";
        String password = "";
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                if (c.getName().equals("username"))
                    username = URLDecoder.decode(c.getValue(), "utf-8");
                if (c.getName().equals("password"))
                    password = URLDecoder.decode(c.getValue(), "utf-8");
            }
        }
    %>
    <form name="loginForm" action="dologin.jsp" method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="username" value="<%=username %>"/></td>
            </tr>
            <tr>
                <td>密码:</td>
                td><input type="password" name="password" value="<%=password %>"/></td>
            </tr>
            <tr>
                <td colspan="2"><input type="checkbox" name="isUseCookie" checked="checked"/>十天内记住我的登录状态</td>
            </tr>
            <tr>
                <td colspan="2" align="center"><input type="submit" value="登录"/><input type="reset" value="取消"/></td>
            </tr>
        </table>
    </form>
</body>

users.jsp

<%@ page language="java" import="java.util.*,java.net.*" contentType="text/html; charset=utf-8" %>

<body>
    <%
        request.setCharacterEncoding("utf-8");
        String username = "";
        String password = "";
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                if (c.getName().equals("username"))
                    username = URLDecoder.decode(c.getValue(), "utf-8");
                if (c.getName().equals("password"))
                    password = URLDecoder.decode(c.getValue(), "utf-8");
            }
        }
    %><br>
    用户名:<%=username %><br>
    密码:<%=password %><br>
</body>

指令和动作

include 指令与动作

指令与动作的区别

date.jsp

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" %>
<%@ page import="java.text.*" %>
<%
    Date d = new Date();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
    String s = sdf.format(d);
    out.println(s);
%>

include_command.jsp

<%@ include file="date.jsp" %>

include_action.jsp

<jsp:include page="date.jsp" flush="false"/>

forward 动作

user.jsp

<body>
    <%
        request.setCharacterEncoding("utf-8");
        String username = "";
        String password = "";
        String email = "";
        if (request.getParameter("username") != null) 
            username = request.getParameter("username");
        if (request.getParameter("password") != null) 
            password = request.getParameter("password");
        if (request.getParameter("email") != null) 
            email = request.getParameter("email");
    %>
    用户名:<%=username %><br>
    密码:<%=password %><br>
    电子邮箱:<%=email %><br>
</body>

login.jsp

<body>
    <form name="loginForm" action="forward.jsp" method="post">
        <table>
            <tr>
                <td>用户名:</td>
                <td><input type="text" name="username"/></td>
            </tr>
            <tr>
                <td>密码:</td>
                <td><input type="password" name="password"/></td>
            </tr>
            <tr>
                <td colspan="2"><input type="submit" value="登录"/></td>
            </tr>
        </table>
    </form>
</body>

forward.jsp

<body>
    <jsp:forward page="user.jsp"/>
    <!--<% request.getRequestDispatcher("user.jsp").forward(request, response); %>-->
</body>

param 动作

forward 中加入传递参数

<body>
    <jsp:forward page="user.jsp">
        <jsp:param value="admin@123.net" name="email"/>
        <jsp:param value="888888" name="password"/>
    </jsp:forward>
</body>

相关文章

网友评论

      本文标题:Java Web 基础 - JSP

      本文链接:https://www.haomeiwen.com/subject/ppjsaftx.html