Java Web 基础 - JSP

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 脚本注释


<%-- 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 + "    ");
            out.println("
"); } } %> <% 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 + "    ";
            s += "
"; } 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.*" %>


    JSP


    <%
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String s = sdf.format(new Date());
    %>
    today: <%=s%>


内置对象

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

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

out 对象

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


    <%
        out.println("

静夜思

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

request 对象

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


    

request内置对象

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

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


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("

response内置对象

"); out.println("
"); // 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

    10
    

page1


    <%
        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)%>
Session的ID编号:<%=session.getId()%>
从Session中获取用户名:<%=session.getAttribute("username") %>
跳转到Session_page2.jsp

page2


    
<% //SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); //Date d = new Date(session.getCreationTime()); //session.setAttribute("username", "admin"); %> Session的ID编号:<%=session.getId()%>
从Session中获取用户名:<%=session.getAttribute("username") %>
Session中保存的属性有: <% String[] names = session.getValueNames(); for (int i = 0; i < names.length; i++) { out.println(names[i] + "  "); } %>

application 对象

  • ServletContext 类的实例,实现了用户间数据共享,可存放全局变量;
  • 创建于服务器启动,终止于服务器关闭(服务器启动关闭决定 application 对象);
  • 在用户前后连接、或不同用户之间的连接中,可以对 application 对象的同一属性进行操作;
  • 任何地方对 application 对象属性的操作,都影响其他用户对此的访问。

    <%
        application.setAttribute("city", "北京");
        application.setAttribute("postcode", "10000");
        application.setAttribute("email", "[email protected]");
    %>
    所在城市是:<%=application.getAttribute("city") %>
application中的属性有:<% Enumeration attributes = application.getAttributeNames(); while (attributes.hasMoreElements()) { out.println(attributes.nextElement() + "  "); } %>
JSP(SERVLET)引擎名及版本号:<%=application.getServerInfo() %>

page 对象

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

pageContext 对象

  • 提供了对 JSP 页面内所有对象及命名空间的访问(汇集了页面中的所有功能);
  • 可以访问到本页所在的 Session,可以取本页所在的 application 的某一属性值;
  • 本类名也为pageContext

    

pageContext内置对象


用户名是:<%=pageContext.getSession().getAttribute("username") %>
<% // 跳转到注册页面 // pageContext.forward("reg.jsp"); pageContext.include("include.jsp"); %>

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" %>

    <%
        System.out.println(100 / 0); //抛出运行时异常,算数异常
    %>

error_page

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

    异常的消息是:<%=exception.getMessage()%>
异常的字符串描述:<%=exception.toString()%>

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 + "/";
%>


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


<% String loginUser = ""; if (session.getAttribute("loginUser") != null) loginUser = session.getAttribute("loginUser").toString(); %> 欢迎您<%=loginUser%> ,登录成功!

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

登录失败!请检查用户或者密码!
返回登录

JSP 状态管理

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

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

  • Cookie
  • Session

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

dologin.jsp

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


    <%
        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);      // 重新保存。
                    }
                }
            }
        }
    %>
    查看用户信息

login.jsp

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


    <%
        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");
            }
        }
    %>
    
td>
用户名:
密码:
十天内记住我的登录状态

users.jsp

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


    <%
        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");
            }
        }
    %>
用户名:<%=username %>
密码:<%=password %>

指令和动作

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


forward 动作

user.jsp


    <%
        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 %>
密码:<%=password %>
电子邮箱:<%=email %>

login.jsp


    
用户名:
密码:

forward.jsp


    
    

param 动作

forward 中加入传递参数


    
        
        
    

你可能感兴趣的:(Java Web 基础 - JSP)