JSP

JSP全名为Java Server Pages,其根本是一个简化的Servlet设计,实现了在Java当中使用HTML标签。

JSP指令

  • page指令,通常位于jsp页面的顶端,同一个页面可以有多个page指定。
  • include指令,将一个外部文件嵌套到当前JSP文件中,同时解析这个页面中的JSP语句。
  • taglib指令,使用标签库定义新的自定义标签,在JSP页面中启动定制行为。
page指令:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
属性描述默认值
language指定jsp页面使用的脚本语言java
import通过该属性来引用脚本语言中使用到的类文件
contentType用来指定JSP页面所采用的编码方式text/html,utf-8

Jsp脚本

在JSP页面中执行的java代码。

语法:<% Java代码%>

就是在<% %>里嵌入Java代码,这里的Java代码和我们一般的Java代码没有什么区别,所以每一条语句同样要以”;”结束,这和表达式是不相同的 语法:<% code %> 脚本的本质:就是将代码插入到Servlet的service方法中。

Jsp声明

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

语法:<%! Java代码%>

就是允许用户定义Servlet中的变量、方法 语法:<%! code %> 例如:

Jsp表达式

在JSP页面中执行的表达式。
语法:<%=表达式> 表达式不以分号结束。

Jsp表达式可以调用Jsp声明中声明的变量或方法。

Jsp表达式是对数据的表示,系统将其作为一个值进行计算。 语法:<%= expression %> 例如:<%= user.getName()%> 表达式的本质:在将JSP页面转换成Servlet后,使用out.print()将表达式的值输出。这样如果user.getName()的返回值是”liky”, 那么实际上在servlet中就将转换成out.print(“liky”); 因此这里要注意以下两点:

  1. 如果表达式是调用一个方法,那么这个方法必须要有返回值,而不应是void,也就是说void getName()这样的方法是不能被调用的。
  2. 在方法的后面不能有分号;例如<%=getName();%>这是不允许的。

Jsp页面生命周期

Created with Raphaël 2.1.2 用户发出请求index.jsp 是否是第一次请求? JSP引擎把该JSP文件转换成为一个Servlet,生成字节码文件,并执行jspInit() 生成字节码文件 解析执行,jspService() yes no

jspService()方法被调用来处理客户端的请求。对每一个请求,JSP引擎创建一个新的线程来处理该请求。如果有多个客户端同时请求该JSP文件,则JSP引擎会创建多个线程。每个客户端请求对应一个线程。以多线程方式执行可以大大降低对系统的资源需求,提高系统的并发量及响应时间。但也要注意多线程的编程带来的同步问题,由于该Servlet始终驻于内存,所以响应是非常快的。
测试了一下,在index.jsp页面中,写了Jsp脚本,Jsp声明,Jsp表达式。
执行程序,访问index.jsp后,在 D:\program Files\apache-tomcat-8.5.11\work\Catalina\localhost\JspDemo\org\apache\jsp 路径下确实生成了index_jsp.java文件。

<body>
    <h1>JSP生命周期</h1>
    <hr>
    <%
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        String s = sdf.format(new Date());
     %>
     <%!
        String rain="今天下雨了";
        String dalei() {
            String lei ="好响的雷";
            return lei;
        }
      %>
     今天是:<%=s %>;
  </body>

Jsp脚本的内容写在了_jspService()方法中了。Jsp声明的内容写在了类的最前面。Jsp表达式变成了_jspService()方法中一句out.print(s );

index_jsp.java

/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/8.5.11
 * Generated at: 2017-08-25 22:03:48 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.text.SimpleDateFormat;
import java.util.*;

public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {


        String rain="今天下雨了";
        String dalei() {
            String lei ="好响的雷";
            return lei;
        }

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private static final java.util.Set<java.lang.String> _jspx_imports_packages;

  private static final java.util.Set<java.lang.String> _jspx_imports_classes;

  static {
    _jspx_imports_packages = new java.util.HashSet<>();
    _jspx_imports_packages.add("javax.servlet");
    _jspx_imports_packages.add("java.util");
    _jspx_imports_packages.add("javax.servlet.http");
    _jspx_imports_packages.add("javax.servlet.jsp");
    _jspx_imports_classes = new java.util.HashSet<>();
    _jspx_imports_classes.add("java.text.SimpleDateFormat");
  }

  private volatile javax.el.ExpressionFactory _el_expressionfactory;
  private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public java.util.Set<java.lang.String> getPackageImports() {
    return _jspx_imports_packages;
  }

  public java.util.Set<java.lang.String> getClassImports() {
    return _jspx_imports_classes;
  }

  public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
    if (_el_expressionfactory == null) {
      synchronized (this) {
        if (_el_expressionfactory == null) {
          _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
        }
      }
    }
    return _el_expressionfactory;
  }

  public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
    if (_jsp_instancemanager == null) {
      synchronized (this) {
        if (_jsp_instancemanager == null) {
          _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
        }
      }
    }
    return _jsp_instancemanager;
  }

  public void _jspInit() {
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {

    final java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
      return;
    }

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html; charset=UTF-8");
      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;

      out.write("\r\n");
      out.write("\r\n");
      out.write("\r\n");

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

      out.write("\r\n");
      out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <base href=\"");
      out.print(basePath);
      out.write("\">\r\n");
      out.write("    \r\n");
      out.write("    <title>My JSP 'index.jsp' starting page</title>\r\n");
      out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
      out.write("\t<meta http-equiv=\"expires\" content=\"0\">    \r\n");
      out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
      out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
      out.write("\t<!--\r\n");
      out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
      out.write("\t-->\r\n");
      out.write("  </head>\r\n");
      out.write("  \r\n");
      out.write("  <body>\r\n");
      out.write("  \t<h1>JSP生命周期</h1>\r\n");
      out.write("  \t<hr>\r\n");
      out.write("    ");

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        String s = sdf.format(new Date());

      out.write("\r\n");
      out.write("     ");
      out.write("\r\n");
      out.write("     今天是:");
      out.print(s );
      out.write("\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try {
            if (response.isCommitted()) {
              out.flush();
            } else {
              out.clearBuffer();
            }
          } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

使用表达式和脚本的方式实现九九乘法表

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'exercise.jsp' starting page</title>

    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>

  <body>
    <%!
       //返回九九乘法表对应的HTML代码,通过表达式来调用,在页面上显示 
       String printMultiTable1()
       {
          String s = "";
          for(int i=1;i<=9;i++)
          {
             for(int j=1;j<=i;j++)
             {
                s+=i+"*"+j+"="+(i*j)+"&nbsp;&nbsp;&nbsp;&nbsp;";
             }
             s+="<br>"; //追加换行标签
          }
          return s;
       }

       //JSP内置out对象,使用脚本方式调用,打印九九乘法表
       void printMultiTable2(JspWriter out) throws Exception
       {
           for(int i=1;i<=9;i++)
           {
             for(int j=1;j<=i;j++)
             {
                out.println(i+"*"+j+"="+(i*j)+"&nbsp;&nbsp;&nbsp;&nbsp;");
             }
             out.println("<br>"); //追加换行标签
          }
       }

    %>
    <h1>九九乘法表</h1>
    <hr>
    <%=printMultiTable1()%>
    <br>
    <% printMultiTable2(out);%>
    <br>

  </body>
</html>

get与post区别

<form name="regForm" action="动作" method="提交方式"></form>
表单有两种提交方式:get与post。

  1. get:以明文的方式通过URL提交数据,数据在URL中可以看到。提交的数据不超过2KB。安全性较低但效率比post方式高。适合提交数据量不大,安全性不高的数据。比如:搜索、查询等功能。
  2. post:将用户提交的信息封装在HTML HEADER内。适合提交数据量大,安全性高的用户信息。比如:注册、修改、上传等功能。

Jsp内置对象

JSP内置对象是Web容器创建的一组对象,不使用new关键字就可以使用的内置对象。
JSP九大内置对象为:out request response session application page pagecontext exception config

out对象

out对象是JspWriter类的实例,是向客户端输出内容常用的对象。
常用方法如下:

  1. void println() 向客户端打印字符串
  2. void clear() 清除缓冲区的内容,如果在flush之后调用会抛出异常。
  3. void clearBuffer() 清除缓冲区的内容,如果在flush之后调用不会抛出异常。
  4. void flush() 将缓冲区的内容输出到客户端
  5. int getBufferSize() 返回缓冲区以字节数的大小,如不设缓冲区则为0
  6. int getRemaining() 返回缓冲区还剩余多少可用
  7. boolean isAutoFlush() 返回缓冲区满时,是自动清空还是抛出异常
  8. void close() 关闭输出流
  <body>
    <h1>out内置对象</h1>
    <% 
       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对象,客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。request对象具有请求域,即完成客户端的请求之前,该对象一直有效。常用方法如下:

  1. String getParameter(String name) 返回name指定参数的参数值
  2. String[] getParameterValues(String name) 返回包含参数name的所有值的数组
  3. void setAttribute(String,Object) 存储此请求中的属性
  4. Object getAttribute(String name) 返回指定属性的属性值
  5. String getContentType() 得到请求体的MIME类型
  6. String getProtocol() 返回请求用的协议类型及版本号
  7. String getServerName() 返回接受请求的服务器主机名

测试getParameter和getParameterValues方法
reg.jsp,建立一个form表单,input文本框输入用户名,checkbox选择爱好。在request.jsp文件中接收参数

<form name="regForm" action="request.jsp" method="post">
    <table>
      <tr>
        <td>用户名:</td>
        <td><input type="text" name="username"/></td>
      </tr>
      <tr>
        <td>爱好:</td>
        <td>
           <input type="checkbox" name="favorite" value="read">读书
           <input type="checkbox" name="favorite" value="music">音乐
           <input type="checkbox" name="favorite" value="movie">电影
           <input type="checkbox" name="favorite" value="internet">上网
        </td>
      </tr>
      <tr>
         <td colspan="2"><input type="submit" value="提交"/></td>
      </tr>
    </table>
    </form>

request.jsp页面接收参数,注意方法中的名字与reg.jsp表单中的名字对应。

用户名:<%=request.getParameter("username") %><br>   
爱好 :<%            
    String[] favorites = request.getParameterValues("favorite");
    for(int i=0;i<favorites.length;i++)
    {
       out.println(favorites[i]+"&nbsp;&nbsp;");
    }

%> <br>

注册页面
request页面
这时如果用户名输入中文的用户名,在request.jsp页面得到的用户名出现乱码。
乱码

Tomcat在提交表单的时候,默认使用ISO-8859-1这个字符集,要想更正中文乱码问题,可以在接收参数之前,使用request.setCharacterEncoding(“”)。设置的值应于提交表单上页面设置的字符集编码要一致。
解决方案:

<% 
   request.setCharacterEncoding("utf-8"); //解决中文乱码问题,

%>

前面request.getParameter()是使用post方式获取的,当然也可以接收get方式提交过来的参数。
下面演示一个通过URL地址来传递用户名。在reg页面下添加以下代码。
<a href="request.jsp?username=lisi">测试URL传参数</a>
此时,点击这个a标签,想要跳转到request.jsp页面。然而,HTTP Status 500。
原来request.jsp页面还在接收favorite。
request.getParameterValues("favorite")
但通过URL传参数的时候,只传了用户名的信息,没有传爱好的信息。
所以这里可以加上判空的语句。在传值的时候加上判空语句是很重要的

if(request.getParameterValues("favorite")!=null)
{
    String[] favorites = request.getParameterValues("favorite");
    for(int i=0;i<favorites.length;i++)
    {
       out.println(favorites[i]+"&nbsp;&nbsp;");
    }
} 

接下来,测试在URL传参时,传递中文
<a href="request.jsp?username=李四">测试URL传参数</a>
发现又出现了乱码。这种情况下,req.setCharacterEncoding无法解决。
对于这种中文乱码,可以通过设置Tomcat服务器中的server.xml,找到Connector标签,加上URIEncoding=”utf-8”

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" URIEncoding="utf-8"/>

重启后生效。

request其他方法
<% 
   request.setAttribute("password", "123456");//设置请求中的password属性
%>
密码:<%=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>

结果:
用户名:李四
爱好 :read
密码:123456
请求体的MIME类型:application/x-www-form-urlencoded
协议类型及版本号: HTTP/1.1
服务器主机名 :localhost
服务器端口号:8080
请求文件的长度 :41
请求客户端的IP地址:0:0:0:0:0:0:0:1
请求的真实路径:D:\program Files\apache-tomcat-8.5.11\webapps\JspDemo\request.jsp
请求的上下文路径:/JspDemo

response对象

response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。response对象具有页面作用域,即访问一个页面时,该页面内的response对象只能对这次访问有效,其他页面的response对象对当前页面无效。常用方法如下:

  • String getCharacterEncoding() 返回响应的是何种字符编码
  • void setContentType(String type) 设置响应的MIME类型
  • PrintWriter getWriter() 返回可以向客户端输出字符的一个对象(注意比较:PrintWriter与内置对象out对象的区别。getWriter()的输出总是在out的前面。)
  • sendRedirect(java.lang.String location) 重定向客户端的请求
<%@ 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对象");
    //这时,outer输出的内容在上面。如果想按正常顺序输出,可以在out输出后,加上flush方法。清空缓冲区,并把前面缓冲区的内容写在浏览器上。

    response.sendRedirect("reg.jsp");//请求重定向
%>
请求重定向与请求转发的区别
  • 请求重定向:客户端行为,response.sendRedirect(),从本质上讲等同于两次请求,前一次请求对象不会保存,地址栏的URL地址会改变。
  • 请求转发:服务器行为,request.getRequestDispatcher().forward(req,resp);是一次请求,转发后请求对象会保存,地址栏的URL地址不会改变。

例子,在reg.jsp的表单提交到response.jsp页面,response.jsp页面分别做请求重定向和请求转发。都跳转到request.jsp页面中。观察reg.jsp中的username和favorite数据能否被request.jsp页面接收。

<form name="regForm" action="response.jsp" method="post">
    <table>
        <tr>
          <td>用户名:</td>
          <td><input type="text" name="username"/></td>
        </tr>
        <tr>
          <td>爱好:</td>
          <td>
             <input type="checkbox" name="favorite" value="read">读书
             <input type="checkbox" name="favorite" value="music">音乐
             <input type="checkbox" name="favorite" value="movie">电影
             <input type="checkbox" name="favorite" value="internet">上网
          </td>
        </tr>
        <tr>
           <td colspan="2"><input type="submit" value="提交"/></td>
        </tr>
    </table>
</form>

response.jsp

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

    //请求重定向
    response.sendRedirect("request.jsp");
    //请求转发
   /*  request.getRequestDispatcher("request.jsp").forward(request, response); */
%>

request.jsp

<body>
<h1>request内置对象</h1>
    <% 
       request.setCharacterEncoding("utf-8"); //解决中文乱码问题,无法解决URL传递中文出现的乱码问题。
    %>
    用户名:<%=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>
</body>

这里写图片描述
请求重定向结果:
这里写图片描述
请求转发结果:
这里写图片描述

session对象

什么是session
  • session表示客户端与服务器的一次会话
  • Web中的session指的是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间
  • 从上述定义中可以看到,session实际上是一个特定的时间概念。
  • 在服务器的内存中保存着不同用户的session。
session对象
  • session对象是一个JSP内置对象
  • session对象在第一个JSP页面被装载时自动创建,完成一次客户端与服务器会话管理。
  • 从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。
  • 当一个客户访问一个浏览器时,可能会在服务器的几个页面之间切换,服务器应当通过某种办法知道这是一个客户,就需要session对象。
  • session对象是HttpSession类的实例。

session对象常用方法如下:
- long getCreationTime():返回SESSION创建时间
- public String getId():返回SESSION创建时JSP引擎为它设的唯一ID
- public Object setAttribute(String name, Object value):使用指定名称将对象绑定到此会话
- public Object getAttribute(String name):返回与此会话中的指定名称绑定在一起的对象,如果没有对象绑定在该名称下,则返回null
- String[] getValueNames():返回一个包含此SESSION中所有可用属性的数组
- int getMaxInactiveInterval():返回两次请求间隔多长时间此SESSION被取消(单位为秒)

例子:
session_page1.jsp

<h1>session内置对象</h1>
    <hr>
    <% 
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
      Date d = new Date(session.getCreationTime());//session创建时间
      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>
    <!-- 用于测试在session_page2.jsp可以得到session_page1.jsp中设置的username等属性 -->

session_page2.jsp

<h1>session内置对象</h1>
 <h1>session内置对象</h1>
<hr>
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;");
                 }

%> <br>

这里写图片描述

session的生命周期
  • 创建:当客户端第一次访问某个jsp或者Servlet时,服务器会为当前会话创建一个SessionId,每次客户端向服务器发送请求时,都会将此SessionId携带过去,服务端会对此SessionId进行校验。
  • 活动:某次会话当中通过超链接打开的新页面属于同一次会话。
  • 只要当前会话页面没有全部关闭,重新打开新的浏览器窗口访问同一项目资源时属于同一次会话。
  • 除非本次会话的所有页面都关闭后再重新访问某个Jsp或者Servlet将会创建新的会话。
    • 注意原有会话还存在,只是这个旧的SessionId仍然存在于服务端,只不过再也没有客户端会携带它然后交予服务端校验。除非原有会话超时,原有会话才会结束。
  • 销毁:
    • 调用session.invlidate()方法
    • Session过期(超时)
    • 服务器重启

Tomcat默认session超时时间为30分钟。
设置session超时有两种方式:
1. session.setMaxInactiveInterval(时间); 单位是秒
2. 在web.xml配置,单位是分钟

<session-config>
    <session-timeout>10</session-timeout>
</session-config>

application对象

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

常用方法:
- getAttribute/setAttribute
- Enumeration getAttributeNames() 返回所有可用属性名的枚举
- String getServerInfo() 返回JSP引擎名及版本号

<h1>application内置对象</h1>
    <% 
       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>

运行结果:
这里写图片描述

page对象

page对象就是指当前JSP页面本身,有点像类中的this指针,它是java.lang.Object类的实例。
常用方法如下,与Object类的方法一致:
- class getClass()
- int hashCode()
- boolean equals(Object obj)
- void copy(Object obj)
- Object clone()
- String toString()
- void notify() 唤醒一个等待的线程
- void notifyAll() 唤醒所有等待的线程
- void wait(int timeout) 使一个线程处于等待直到timeout结束或被唤醒
- void wait() 使一个线程处于等待直到被唤醒

<h1>page内置对象</h1>
当前page页面对象的字符串描述:<%=page.toString() %><br>  

输出结果:
当前page页面对象的字符串描述:org.apache.jsp.page_jsp@540bfa68

输出了类的全名+hashcode
page.jsp被解析成了page_jsp.java,在Tomcat的work目录下。

pageContext对象

  • pageContext对象提供了对JSP页面内所有的对象及名字空间的访问
  • pageContext对象可以访问到本页所在的session,也可以取本页面所在的application的某一属性值
  • pageContext对象相当于页面所有功能的集大成者
  • pageContext对象的本类名也叫pageContext

常用方法:

  • JspWriter getOut() 返回当前客户端响应被使用的JspWrite流(out)
  • HttpSession getSession()
  • Object getPage()
  • ServletRequest getRequest()
  • ServletResponse getResponse()
  • void setAttribute(String name,Object attribute)
  • Object getAttribute(String name,int scope)
  • int getAttributeScope(String name) 返回某属性的作用范围
  • void forward(String relativeUrlPath) 使当前页面重导到另一页面
  • void include(String relativeUrlPath) 在当前位置包含另一文件

例子,先访问session_page1页面,在访问当前页面。可以访问到session_page1中session的属性值

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

config对象

config是在一个Servlet初始化时,JSP引擎向它传递信息的,此信息包括Servlet初始化时所要用到的参数以及服务器有关信息

exception对象

exception对象是一个异常对象,当一个页面在运行过程中发生了异常,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象。
方法:

  • String getMessage() 返回描述异常的消息
  • String toString() 返回关于异常的简短描述消息

JSP状态管理

http协议的无状态性

无状态是指,当浏览器发送请求给服务器的时候,服务器响应客户端请求。但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道它就是刚才那个浏览器。服务器不会去记住你。

cookie概述

保存用户状态的两种机制:
- Session
- Cookie
Cookie是web服务器保存在客户端的一系列文本信息。
Cookie的典型应用场景:

  1. 判定注册用户是否已经登录网站。是否在下次登录时保留登录信息
  2. 购物车的处理。用户可能在一段时间内访问同一家网站,在不同页面间选择不同的商品,可以把这些信息保存到客户端的Cookie中。以便最后结账时把这些信息提取出来。

Cookie的作用:
- 对特定对象的跟踪
- 保存用户网页浏览记录与习惯
- 简化登录
安全风险:容易泄露用户信息

Jsp中创建与使用Cookie:

  • 创建Cookie对象,Cookie newCookie = new Cookie(String key,Object value);
  • 写入Cookie对象,response.addCookie(newCookie);
  • 读取Cookie对象,Cookie[] cookies = request.getCookies();

常用方法:

方法名称说明
void setMaxAge(int expiry)设置cookie的有效期,以秒为单位
void setValue(String value)在cookie创建后,对cookie进行赋值
String getName()获取cookie的名称
String getValue()获取cookie的值
int getMaxAge()获取cookie的有效时间,以秒为单位
例子,实现登录的用户名密码保存到cookie

这里写图片描述
login.jsp页面。要实现读取cookie,如果cookie数组中有用户名、密码的cookie信息,则要在访问这个页面时,把信息写入到输入框中。
考虑用户名为中文问题。存入用户名的cookie需要进行编码;读取用户名的cookie需要解码

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>

  <body>
    <h1>用户登录</h1>
    <hr>
    <% 
      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>
</html>

dologin.jsp页面。这里显示登录成功。此页面需要,判断点击登录时是否勾选了记住登录状态复选框。如果勾选了,就要创建用户名、密码的cookie,并写入;没勾选,则要设置用户名、密码的cookie信息失效,并写入cookie。

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'dologin.jsp' starting page</title>

    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>

  <body>
    <h1>登录成功</h1>
    <hr>
    <br>
    <br>
    <br>
    <% 
       request.setCharacterEncoding("utf-8");
       //首先判断用户是否选择了记住登录状态
       String[] isUseCookies = request.getParameterValues("isUseCookie");
       if(isUseCookies!=null&&isUseCookies.length>0)
       {
          //把用户名和密码保存在Cookie对象里面
          String username = URLEncoder.encode(request.getParameter("username"),"utf-8");
          //使用URLEncoder解决无法在Cookie当中保存中文字符串问题
          String password = URLEncoder.encode(request.getParameter("password"),"utf-8");

          Cookie usernameCookie = new Cookie("username",username);
          Cookie passwordCookie = new Cookie("password",password);
          usernameCookie.setMaxAge(864000);
          passwordCookie.setMaxAge(864000);//设置最大生存期限为10response.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>
</html>

users.jsp,显示用户信息。读取用户名、密码的cookie,并显示

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'users.jsp' starting page</title>

    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>

  <body>
    <h1>用户信息</h1>
    <hr>
    <% 
      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>
    <BR>
    <BR>
         用户名:<%=username %><br>
         密码:<%=password %><br>
  </body>
</html>
session与cookie对比

共同点:

  1. 都是用来保存用户状态的机制。
  2. 都会过期,都有生存期限。

区别:

  1. session保存在服务器端内存中;cookie以文本文件的形式保存在客户端
  2. session保存的是Object类型;cookie保存的是字符串类型
  3. session随着会话的结束而将其存储的数据销毁;cookie可以长期的保存在客户端。
  4. session用于保存安全性高的信息;cookie相对保存不重要的信息,如浏览记录等。

JSP指令与动作元素

include指令,包含一个页面

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

include动作

<jsp:include page="URL" flush="true|false"/>
flush:表示被包含的页面是否从缓冲区读取,true使用缓冲。

include指令与include动作比较

这里写图片描述

forward动作

<jsp:forward page="URL" />
等同于 request.getRequestDispatcher(“/url”).forword(req,resp);

param动作

<jsp:param name="参数名" value="参数值" />
常常与forward动作一起使用,作为其子标签。可以添加新的参数,也可以改变前面传过来的参数。

<jsp:forward page="user.jsp">
    <jsp:param name="email" value="jiaxing747@163.com" />
</jsp:forward>

到user.jsp页面的时候,不但可以获取前一个页面的属性,还可以获取email参数的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值