java web学习笔记-jsp篇

Posted coder为

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java web学习笔记-jsp篇相关的知识,希望对你有一定的参考价值。

转载自:http://www.cnblogs.com/happyfans/archive/2015/03/17/4343571.html

1.java web简介

  1.1静态页面与动态页面

  表现形式 所需技术
静态网页 网页内容固定,不会更新 html,css
动态网页 网页内容由程序动态显示,自动更新 html,css,DB,java/c#/php,javascript,xml,主流的动态网页脚本(jsp,asp.net,php)

 

  1.2搭建java web开发环境

    jdk1.7+tomcat7.0+MyEclipse10。关于MyEclipse的安装和配置请参见http://blog.sina.com.cn/s/blog_907043b301016jtp.html。Tomcat服务器是Apache Jakarta的开源项目,是Jsp/Servlet容器。安装Tomcat只需要解压zip包到指定目录即可。新建一个环境变量CATALINA_HOME,变量的值是Tomcat的根目录D:\\Program Files (x86)\\apache-tomcat-7.0.57。全部的环境变量如下:

变量名 变量值
JAVA_HOME D:\\Program Files (x86)\\Java\\jdk1.7.0_40
Path C:\\Program Files\\Microsoft SQL Server\\100\\DTS\\Binn\\;%JAVA_HOME%\\bin;D:\\Program Files\\Sublime Text 3;D:\\Program Files\\mysql\\MySQL Utilities 1.3.6\\
classpath .;%JAVA_HOME%\\lib\\rt.jar;%JAVA_HOME%\\lib\\tools.jar;
CATALINA_HOME D:\\Program Files (x86)\\apache-tomcat-7.0.57

之后我们测试一下Tomcat的首页:

  进入Tomcat服务器根目录下面的bin目录,以管理员方式运行startup.bat,如果运行结果如下就表示Tomcat服务器启动成功。

  注意:不要关闭这个窗口(关闭窗口就意味着关闭了Tomcat服务器,将其最小化)。

在浏览器地址栏输入http://localhost:8080/回车得到如下页面:

  

1.3Tomcat目录结构

  1.4手工编写第一个web应用程序

  在项目文件夹中创建一个index.jsp:

复制代码
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>手工编写的第一个java web项目</title>
 6 </head>
 7 <body>
 8     <h1>这是手工编写的第一个java web项目——jsp</h1>
 9     <hr />
10 </body>
11 </html>
复制代码

  在项目目录中创建一个WEB-INF目录拷贝/webapps/examples/WEB-INFO/web.xm到自己项目的/myJspProject/WEB-INFO中,在/myJspProject/WEB-INFO中创建两个文件夹:classes和lib。最后的项目目录应该是这样:

  测试:浏览器输入:http://localhost:8080/myJspProject/index.jsp回车,运行结果如下:

 解决方法:更改浏览器编码为指定编码:

  1.5WEB-INF目录详解

      该目录是java web应用的安全目录。所谓安全目录就是客户端无法访问只有服务端可以访问的目录。其中web.xml是项目部署文件,classes目录:存放*.class文件,lib目录存放需要的jar包。例如:我们在WEB-INF中创建一个test.html,下面我们通过浏览器访问:

  web.xml配置文件可以配置欢迎页面默认的欢迎页面是项目下面的index.jsp,加入我们需要将项目下的haha.jsp,在/WEB-INF/web.xml的web-app标记中添加以下代码:

1 <welcome-file-list>
2             <welcome-file>/haha.jsp</welcome-file>
3</welcome-file-list>    

  运行结果:

  1.6实用Eclipse编写第一个web应用程序

      注意:如果要使用Eclipse编写java web应用应该使用Eclipse的J2EE版本。并在Eclipse中配置Tomcat服务器Window-Preference-Server-Runtime Environment-Add,然后在WebContent目录下新建jsp文件,按下Ctrl+F11(或者在项目中右键-Run On Server)就可以使用内置浏览器访问建立的网站。

  1.7用MyEclipse编写第一个web应用程序

  在新建项目之前首先在MyEclipse中配置jre和tomcat。步骤Window-Preference-Java-Install JREs-Add;Window-MyEclipse-Servers-Tomcat(注意设置tomcat的jre并将服务器设置为Enabled)。

  接下来在MyEclipse中启动Tomcat服务器:

  

  测试首页http://localhost:8080/证明Tomcat正常启动,我们就可以在MyEclipse中启动和发布Web应用程序了。

  New一个WebProject会生成以下的目录结构(默认在WebRoot目录下有一个index.jsp)。

  发布该WebApp。

  1.8理解项目的虚拟路径

  

    该虚拟路径是可以修改的项目上右键属性-MyEclipse-Web。 

 

    重新部署,浏览器需要使用使用http://localhost:8080/hello/index.jsp访问了。

  1.7修改Tomcat默认端口

    修改conf目录下的server.xml的以下标记:

 <Connector connectionTimeout="20000" port="8888" protocol="HTTP/1.1" redirectPort="8443"/>

2.jsp语法基础

  2.1jsp简介

    jsp的全名是Java Server Page,是一个简化的Servlet设计,它实现了在java当中使用html标记。jsp是一种动态网页技术,符合J2EE标准。jsp和Servlet一样也是在服务器端执行的。

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

平台 特点
jsp 跨平台,安全性高,适合开发大型的、企业级的Web应用、分布式应用(Hadoop)。例如:12306、10086.cn、网上银行
asp.net 简单易学,安全性和跨平台性差
php 简单、高效、成本低、开发周期短,适合中小型企业的Web应用开发(LAMP)

 

  2.3jsp页面元素简介以及page指令

    

    

    page指令语法:

<%@ page 属性1="属性值" 属性2="属性值1,属性值2" 属性n="属性值n"%>
属性 描述 默认值
language jsp页面所使用的脚本语言 java
import 引用脚本语言中所要使用的类文件
contentType 指定jsp页面的编码 text/html,ISO-8859-1

  新建一个java web工程默认的jsp页面开头有一个page指令:

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>

  默认的编码是ISO-8859-1,不支持中文,这里建议使用另一个属性contentType。将第一行改为如下:

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

  这样就支持中文了。

  page指令的全部属性如下:

复制代码
 1 <%@page
 2     [language="Java"]
 3     [extends="package.class"] // 指定JSP页面编译所产生的Java类所继承的父类,或所实现的接口。
 4     [import="package.class│package.*,…"]
 5     [session="true│false"]
 6     [buffer="none│8kb│size kb"]
 7     [autoFlush="true│false"]
 8     [isThreadSafe="true│false"]
 9     [info="text"]
10     [errorPage="relativeURL"] // 指定错误处理页面。因为JSP内建了异常机制支持,所以JSP可以不处理异常。
11     [contentType="mimeType[;charset=characterSet]"│"text/html;charSet=ISO8859-1"]
12     [isErrorPage="true│false"] // 设置本JSP页面是否为错误处理程序。
13 %>
复制代码

    注意:除page指令中的import属性之外,其他属性均只能设置一次。

  2.4jsp注释

  分为3种:html注释,jsp注释,jsp脚本注释。语法:

复制代码
1 <!-- html注释 -->
2 <%-- jsp注释 --%>
3 <%
4         /*这里是jsp脚本注释 有两种*/
5        
6         //单行注释
7 
8          /*多行注释*/
9 %>
复制代码

  例如:

复制代码
 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP \'index.jsp\' starting page</title>
13     <meta http-equiv="pragma" content="no-cache">
14     <meta http-equiv="cache-control" content="no-cache">
15     <meta http-equiv="expires" content="0">    
16     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17     <meta http-equiv="description" content="This is my page">
18     <!--
19     <link rel="stylesheet" type="text/css" href="styles.css">
20     -->
21   </head>
22   
23   <body>
24     <h1>欢迎你</h1>
25     <!-- 这是html注释,客户端可可见 -->
26     <%-- 这是jsp注释,客户端不可见 --%>
27     <%
28         /*这里是jsp脚本注释
29         有两种*/
30         //单行注释
31         /*多行注释*/
32      %>
33   </body>
34 </html>
复制代码

  将项目部署到Tomcat,客户端用浏览器查看源代码:

  2.5jsp脚本

    在jsp页面中执行的java代码。语法:

<% java代码 %>
复制代码
 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP \'index.jsp\' starting page</title>
13     <meta http-equiv="pragma" content="no-cache">
14     <meta http-equiv="cache-control" content="no-cache">
15     <meta http-equiv="expires" content="0">    
16     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17     <meta http-equiv="description" content="This is my page">
18     <!--
19     <link rel="stylesheet" type="text/css" href="styles.css">
20     -->
21   </head>
22   
23   <body>
24     <h1>欢迎你</h1>
25     <hr>
26     <%
27         out.println("通过jsp内置对象out对象打印输出");
28      %>
29   </body>
30 </html>
复制代码

  

  2.6jsp声明

      jsp页面中定义变量或者方法。语法:

<%! java代码 %>

  例如:

1  <%!
2         String s = "张三";    //声明一个String类型的变量
3         int add(int x,int y){    //声明一个返回值为int类型的方法
4             return x+y;
5         }
6   %>

  2.7jsp表达式

    jsp页面中执行的表达式。语法(注意=紧挨着百分号,表达式末尾没有分号):

<%=表达式 %>
复制代码
 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     
12     <title>My JSP \'index.jsp\' starting page</title>
13     <meta http-equiv="pragma" content="no-cache">
14     <meta http-equiv="cache-control" content="no-cache">
15     <meta http-equiv="expires" content="0">    
16     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
17     <meta http-equiv="description" content="This is my page">
18     <!--
19     <link rel="stylesheet" type="text/css" href="styles.css">
20     -->
21   </head>
22   
23   <body>
24     <h1>欢迎你</h1>
25     <hr>
26     <!-- 这是html注释,客户端可可见 -->
27     <%!
28         String s = "张三";    //声明一个String类型的变量
29         int add(int x,int y){    //声明一个返回值为int类型的方法
30             return x+y;
31         }
32      %>
33      你好:<%=s %><br>
34      令x=10,y=5,则x+y = <%=add(10, 5) %>
35   </body>
36 </html>
复制代码

  运行结果:

  2.8jsp页面生命周期

    

    jspService()方法被调用来处理客户端的请求。对每一个请求,JSP引擎创建一个新的线程来处理该请求。如果有多个客户端同时请求你该jsp文件,则jsp引擎会创建多个线程(每一个客户端请求对应一个线程)。以多线程的方式执行可以大大降低对系统的资源需求,提高系统的并发量以及缩短服务器的响应时间——但是同时要注意多线程的同步问题。由于该Servlet常驻内存,所以响应是非常快的。

    当页面没有被访问的时候work目录下没有相关的Servlet。如果页面被访问之后就会在work目录的对应目录生成响应的Servlet。如图:

  打开index_jsp.java会看到以下的初始化方法:

  然后该Servlet常驻内存,创建线程处理每一个客户端的请求。由每一个线程调用_jspService()方法来处理请求。

  如果jsp页面内容发生了改变,jsp引擎就需要重新编译jsp页面。我们修改index.jsp,用浏览器重新访问,则:

 2.9阶段项目(九九乘法表)

复制代码
 1 <%@page import="java.io.IOException"%>
 2 <%@ page language="java" import="java.util.*"
 3     contentType="text/html; charset=utf-8"%>
 4 <%
 5 String path = request.getContextPath();
 6 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 7 %>
 8 
 9 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
10 <html>
11 <head>
12 <base href="<%=basePath%>">
13 
14 <title>My JSP \'multiplicationTable.jsp\' starting page</title>
15 
16 <meta http-equiv="pragma" content="no-cache">
17 <meta http-equiv="cache-control" content="no-cache">
18 <meta http-equiv="expires" content="0">
19 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
20 <meta http-equiv="description" content="This is my page">
21 
22 
23 </head>
24 
25 <body>
26     <h1>九九乘法表</h1>
27     <h2>表达式的方式打印乘法表</h2>
28     <%!
29         //声明表达式
30         String printMultiTable(){
31             StringBuilder s = new StringBuilder();
32             for(int i=1;i<=9;i++){
33                 for(int j=1;j<=i;j++){
34                     s.append(i+" * "+j+" = "+i*j+"\\t");
35                 }
36                 s.append("<br />");//追加换行标记,注意不能使用\\n
37             }
38             return s.toString();
39         }
40      %>
41     <%=printMultiTable() //调用表达式
42      %>
43 
44     <h2>使用脚本的方式打印九九乘法表</h2>
45     <%!
46         //jsp小脚本
47         void printMultiTable2(JspWriter out) throws IOException{
48             StringBuilder s = new StringBuilder();
49             for(int i=1;i<=9;i++){
50                 for(int j =1;j<=i;j++){
51                     s.append(i+" * "+j+" = "+i*j+"\\t");
52                 }
53                 s.append("<br />");
54             }
55             out.println(s.toString());
56         }
57      %>
58 
59     <%
60          //调用脚本
61      printMultiTable2(out);
62       %>
63 </body>
64 </html>
复制代码

  运行结果:

3.jsp内置对象

  3.1jsp内置对象简介

      JSP内置对象是Web容器创建的一组对象,不需要使用new关键字,JSP规范将它们完成了默认初始化(由JSP页面对应Servlet的_jspService()方法来创建这些实例)。例如打印九九乘法表的jsp小脚本中使用的out对象就是jsp内置对象。

复制代码
 1 <%!
 2         //jsp小脚本
 3         void printMultiTable2(JspWriter out) throws IOException{
 4             StringBuilder s = new StringBuilder();
 5             for(int i=1;i<=9;i++){
 6                 for(int j =1;j<=i;j++){
 7                     s.append(i+" * "+j+" = "+i*j+"\\t");
 8                 }
 9                 s.append("<br />");
10             }
11             out.println(s.toString());//这里的out就是jsp内置对象
12         }
13 %>
复制代码

    JSP一共有9个内置对象,其中常用的内置对象有5个,如图所示:

  3.3out对象

    缓冲区(Buffer)就是内存中用来保存临时数据的一块区域。关于缓冲区有一个很形象的例子:比如我们煮好了饭放在锅里,如果我们一粒一粒地来吃米饭就不知道吃到猴年马月,拿来一个碗来一碗一碗吃,岂不快哉!这里的碗就充当了缓冲区的概念。其实IO的本质就是直接操作字节,但是效率太慢所以引入了缓冲区。

    out对象是JspWriter类的一个实例——是向客户端输出内容的常用对象,该对象的常用方法:

复制代码
1 void println(String message);   // 向客户端打印字符串
2 void clear();                   // 清除缓冲区内容,如果在flush之后调用会抛出异常
3 void clearBuffer();             // 清除缓冲区内容,如果在flush之后调用不会抛出异常
4 void flush();                   // 将缓冲区的内容输出到客户端
5 int getBufferSize();            // 返回缓冲区的大小(字节),默认是0
6 int getRemaining();             // 返回缓冲区可用容量
7 boolean isAutoFlush();          // 返回缓冲区满的时候是自动清空还是抛出异常
8 void close();                   // 关闭输出流
复制代码

    下面是一个简单的示例:

复制代码
 1 <h1>JSP的out内置对象</h1>
 2     <%
 3         //jsp脚本
 4         out.println("<h2>静夜思</h2>");
 5         out.println("李白<br /><br />");
 6         out.println("窗前明月光,<br />");
 7         out.println("疑是地上霜。<br />");
 8         out.println("举头望明月,<br />");
 9         out.println("低头思故乡。<hr />");
10      %>
11      <!-- JSP表达式 -->
12      缓冲区大小:<%=out.getBufferSize() %>字节。<br />
13     剩余缓冲区(可用缓冲区):<%=out.getRemaining() %>字节。<br /> 
14     是否自动清空缓冲区:<%=out.isAutoFlush() %><br />
复制代码

  运行结果:

复制代码
 1 <h1>JSP的out内置对象</h1>
 2     <%
 3         //jsp脚本
 4         out.println("<h2>静夜思</h2>");
 5         out.println("李白<br /><br />");
 6         out.println("窗前明月光,<br />");
7 out.flush();//将缓冲区中的内容输出到客户端
8 out.println("疑是地上霜。<br />"); 9 out.println("举头望明月,<br />"); 10 out.println("低头思故乡。<hr />"); 11 %> 12 <!-- JSP表达式 --> 13 缓冲区大小:<%=out.getBufferSize() %>字节。<br /> 14 剩余缓冲区(可用缓冲区):<%=out.getRemaining() %>字节。<br /> 15 是否自动清空缓冲区:<%=out.isAutoFlush() %><br />
复制代码

  如果在第7行强制刷新缓冲区,则输出的页面不会有任何变化,仅仅是可用缓冲区的数量变多了而已【因为flush清空了缓冲区】

复制代码
 1 <%
 2         //jsp脚本
 3         out.println("<h2>静夜思</h2>");
 4         out.println("李白<br /><br />");
 5         out.println("窗前明月光,<br />");
 6         
 7     out.flush();//将缓冲区中的内容输出到客户端
 8     out.clear();//在flush之后调用clear,将会抛出异常
 9     
10         out.println("疑是地上霜。<br />");
11         out.println("举头望明月,<br />");
12         out.println("低头思故乡。<hr />");
13 %>
复制代码

  运行结果:

复制代码
 1  <%
 2         //jsp脚本
 3         out.println("<h2>静夜思</h2>");
 4         out.println("李白<br /><br />");
 5         out.println("窗前明月光,<br />");
 6         
 7     out.flush();//将缓冲区中的内容输出到客户端
 8     out.clearBuffer();//在flush之后调用clearBuffer不会抛出异常
 9     
10         out.println("疑是地上霜。<br />");
11         out.println("举头望明月,<br />");
12         out.println("低头思故乡。<hr />");
13 %>
复制代码

  运行结果:

  3.4post和get提交方式的区别

<form name="regForm" action="处理脚本"  method="提交方式[post|get]"></form>
  • get:以明文的方式通过URL提交数据,提交的数据最大不超过2K。适合提交数据量小,安全性不高的数据【例如:搜索和查询】
  • post:将用户提交的数据封装在URL HEADER内。适合提交数据量大,安全性高的数据【例如:注册、修改、上传】 
  • 下面以用户登录的例子比较两者的区别:
    login.jsp页面
1    请输入用户名和密码:
2     <form  name = "loginForm" action = "dologin.jsp" method = "get">
3     用户名:<input type="text" name="username" value="" maxlength = "15" /><br />
4     密码:<input type="password" name="password" maxlength="16" value="" /><br />
5     <input type="submit" value="提交" />
6     </form>

  处理登录的动作脚本dologin.jsp仅仅是显示一句话"登录成功"。

  运行结果:

  将用户登录表单的get方式改为post。

  3.5request对象

    客户端的请求被封装在request对象中,通过它才能了解到客户端的需求,然后做出响应。它是HttpServletRequest对象的实例。request对象具有请求域,即:完成客户端的请求之前,该对象一直有效。常用方法如下:

复制代码
/* 两个比较常用的方法 */
1 String getParameter(String name); // 返回name指定参数的参数值 2 String[] getParameterValues(String name); // 返回包含name的所有值的数组

3 void setAttribute(String,Object); // 存储此请求中的属性 4 String getContentType(); // 返回请求体的MIME类型 5 Stirng getProtocol(); // 返回请求所用的协议和版本号 6 String getServerName(); // 返回接受请求的服务器的主机名 7 int getServerPort(); // 返回服务器接受此请求所用的端口号 8 String getCharacterEncoding(); // 返回字符编码方式【只能解决post方式的乱码问题】 9 void setCharacterEncoding(); // 设置请求的字符编码方式 10 int getContentLength(); // 返回请求体的长度(字节) 11 String getRemoteAddr(); // 返回发送此请求的客户端IP 12 String getRealPath(String path); // 返回虚拟路径的真实路径 13 String request.getContextPath(); // 返回上下文路径
复制代码

  以用户注册页面为例(用户在注册页reg.jsp完善信息后提交给request.jsp来处理):

  用户注册页reg.jsp

复制代码
 1    请输入相关信息完成注册<br />
 2     <form action="request.jsp" name="regForm" method="post">
 3             用户名:<input type="text" name = "username" /><br />
 4             密码:<input type="password" name = "password" /><br />
 5             爱好:
 6         <input type="checkbox" name = "favorite" value="read"/>读书
 7         <input type="checkbox" name = "favorite" value="music"/>音乐
 8         <input type="checkbox" name = "favorite" value="movie"/>电影
 9         <input type="checkbox" name = "favorite" value="internet"/>上网<br />
10         <input type="submit" value="提交" />  
11     </form>
复制代码

   处理用户注册页的request.jsp

复制代码
 1  <h1>request内置对象</h1><br  />
 2   
 3     用户名:<%=request.getParameter("username") %><br />
 4     密码:<%=request.getParameter("password") %><hr />
 5     爱好:<br />
 6     <%
 7         String[]favorites = request.getParameterValues("favorite");
 8         for(String str:favorites){
 9             out.print(str+"&nbsp;&nbsp;");
10         }
11     %>
复制代码

    运行结果:

  但是以上页面存在一个问题:假如我们在用户名中输入中文:

  这时只要再request.jsp中设置字符集和reg.jsp一样即可:

复制代码
 1 <h1>request内置对象</h1><br  />
 2     <!-- 设置字符集,防止出现中文乱码 -->
 3     <% request.setCharacterEncoding("utf-8"); %>

4 用户名:<%=request.getParameter("username") %><br /> 5 密码:<%=request.getParameter("password") %><hr /> 6 爱好:<br /> 7 <% 8 String[]favorites = request.getParameterValues("favorite"); 9 for(String str:favorites){ 10 out.print(str+"&nbsp;&nbsp;"); 11 } 12 %>
复制代码

  除了可以使用表单的方式传递数据给request对象,也可以使用URL传参的方式传递数据给request对象:

  reg.jsp

<a href="request.jsp?username=root&password=toor&favorite=read&favorite=internet">测试URL传参</a>

  request.jsp(不变)

复制代码
 1 <h1>request内置对象</h1><br  />
 2     <!-- 设置字符集,防止出现中文乱码 -->
 3     <% request.setCharacterEncoding("utf-8"); %>
 4     用户名:<%=request.getParameter("username") %><br />
 5     密码:<%=request.getParameter("password") %><hr />
 6     爱好:<br />
 7     <%
 8     String[]favorites;
 9     if((favorites=request.getParameterValues("favorite"))!=null){
10         for(String str:favorites){
11             out.print(str+"&nbsp;&nbsp;");
12         }
13     }
14    %>
复制代码

  运行结果:

  如果我们在URL传参中传入了中文数据,同样会出现乱码问题:

<a href="request.jsp?username=你好&password=toor&favorite=read&favorite=internet">测试URL传参</a>

  此时通过request.setCharacterEncoding()方法就无法解决乱码问题了【一个良好的解决方案是修改tomcat的配置文件server.xml】

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

向request对象中添加键值对:

reg.jsp:

复制代码
 1   请输入相关信息完成注册<br />
 2     <form action="request.jsp" name="regForm" method="post">
 3             用户名:<input type="text" name = "username" /><br />
 4            密码:<input type="password" name = "password" /><br />
 5             爱好:
 6         <input type="checkbox" name = "favorite" value="read"/>读书
 7         <input type="checkbox" name = "favorite" value="music"/>音乐
 8         <input type="checkbox" name = "favorite" value="movie"/>电影
 9         <input type="checkbox" name = "favorite" value="internet"/>上网<br />
10         <input type="submit" value="提交" />  
11     </form>
复制代码

  request.jsp

复制代码
 1 <h1>request内置对象</h1><br  />
 2     <!-- 设置字符集,防止出现中文乱码 -->
 3     <% request.setCharacterEncoding("utf-8"); %>
 4     <%
 5      //在request对象中保存一个email属性
 6     request.setAttribute("email","io@gmail.com");
 7    
 8      %>
 9     用户名:<%=request.getParameter("username") %><br />
10     密码:<%=request.getParameter("password") %><hr />
11     爱好:<br />
12     <%
13     String[]favorites;
14     if((favorites=request.getParameterValues("favorite"))!=null){
15         for(String str:favorites){
16             out.print(str+"&nbsp;&nbsp;");
17         }
18     }
19      %>
20   <br />邮箱:<%=request.getAttribute("email") %>  
复制代码

  运行结果:

复制代码
 1  <h1>request内置对象</h1><br  />
 2     <!-- 设置字符集,防止出现中文乱码 -->
 3     <% request.setCharacterEncoding("utf-8"); %>
 4     <%
 5      //在request对象中保存一个email属性
 6     request.setAttribute("email","io@gmail.com");
 7    
 8      %>
 9     用户名:<%=request.getParameter("username") %><br />
10     密码:<%=request.getParameter("password") %><hr />
11     爱好:<br />
12     <%
13     String[]favorites;
14     if((favorites=request.getParameterValues("favorite"))!=null){
15         for(String str:favorites){
16             out.print(str+"&nbsp;&nbsp;");
17         }
18     }
19      %>
20   <br />邮箱:<%=request.getAttribute("email") %>  <hr />
21   请求体的MIME类型:<%=request.getContentType() %><br />
22   请求体的协议及版本号:<%=request.getProtocol() %><br />
23   服务器主机名:<%=request.getServerName() %><br />
24   服务器端口号:<%=request.getServerPort() %><br />
25   请求的字符编码:<%=request.getCharacterEncoding() %><br />
26   请求的文件长度:<%=request.getContentLength() %>字节<br />
27   请求的客户端的IP:<%=request.getRemoteAddr() %><br />
28   请求的真实路径:<%=request.getRealPath("request.jsp") %><br />
29   请求的上下文路径:<%=request.getContextPath() %>
复制代码

  运行结果:

  3.6response对象

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

1 String getCharacterEncoding();     // 返回响应所用的编码
2 void setContentType();             // 设置响应的MIME类型
3 PrintWriter getPrintWriter();      // 返回一个可以向客户端输出字符的对象【注意区别于out内置对象】
4 sendRedirect(String location);     // 重定向客户端的请求

  response.jsp

复制代码
 1 <%@page import="java.io.PrintWriter"%>
 2 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
 3 <%
 4     response.setContentType("text/html;charset=utf-8");//设置响应的MIME类型
 5     
 6     out.println("<h1>response内置对象</h1><hr />");
 7     
 8     PrintWriter outer = response.getWriter();//获得输出流对象
 9     outer.println("我是response对象生成的outter对象,在页面中总是在前面输出");
10 %>
复制代码

  运行结果:

  运行结果很是奇怪:明明out对象的输出在代码中位于前面。但是结果却是PrintWriter的打印结果在前面,根本原因就是:PrintWriter的对象的输出总是在最前面。如果我们需要让标题先输出,可以使用内置对象out的flush()方法强制刷新缓冲,向页面输出——保证标题出现在最前面。

  请求重定向——当用户请求response.jsp的时候马上跳转到login.jsp

<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<%
    response.sendRedirect("login.jsp"); // 请求重定向
%>

  3.7请求重定向与请求转发的区别

  • 请求重定向:客户端行为response.sendResponse(),从本质上讲相当于两次请求,前一次的请求对象不会保存,浏览器的URL栏会改变。
  • 请求转发:服务器行为request.getRequestDipatcher().forword(req,resp);是一次请求,转发后请求对象会被保存,浏览器的URL不会改变。
  • 例如还是用原来的例子:我们在reg.jsp中指定处理页面的脚本是response.jsp而在response.jsp中我们重定向到request.jsp。观察request.jsp的输出:

  如果我们在response.jsp中使用请求转发:

1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
2 <%
3     //请求转发
4     request.getRequestDispatcher("request.jsp").forward(request, response);
5 %>

  运行结果:

  3.8session对象

    Session客户端与服务器的一次会话。Web中的Session表示用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间——也就是用户浏览这个网站所花费的时间。在服务器的内存中保存着不同用户的Session。

  session对象的常用方法:

复制代码
1 long getCreationTime();                          // 返回session的创建时间
2 String getId();                                  // 返回session创建时JSP引擎为它设定的唯一ID号
3 Object setAttribute(String name,Object value);   // 使用指定名称将对象绑定到此会话
4 Object getAttribute(String name);                // 返回此会话中的指定名称绑定在一起的对象,如果没有对象绑定在该名称下则返回null
5 String[] getValueNames();                        // 返回一个包含此Session所有可用属性的数组
6 int getMaxInactiveInterval();                    // 返回两次请求间隔多长时间此session被取消【单位:秒】
复制代码

  sesseion_page1.jsp

复制代码
 1    <h1>session内置对象</h1>
 2     <h2>session_page1.jsp</h2>
 3     <%
 4         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
 5         String date = sdf.format(new Date(session.getCreationTime()));
 6         out.print("session的创建时间:" + date);
 7         session.setAttribute("username", "admin"); // 向session中设置属性
 8      %>
 9    <br />Session的ID号:<%=session.getId() %><br />
10    从session中获取用户名:<%=session.getAttribute("username") %>
11    
12    <a href="session_page2.jsp" target="_blank">以新窗口的方式打开session_page2.jsp</a>
复制代码

  session_page2.jsp

复制代码
1     <h2>session_page2.jsp</h2>
2     <% 
3         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 
4         String date = sdf.format(new Date(session.getCreationTime())); 
5         out.print("session的创建时间:" + date); 
6      %>
7    <br />Session的ID号:<%=session.getId() %><br />
8    从session中获取用户名:<%=session.getAttribute("username") %>
复制代码

  运行结果:

  可以获取session中保存的属性集合以及设置session的有效期:

复制代码
 1  <%      
 2         session.setMaxInactiveInterval(5);//设置session的有效期为5s
 3         
 4         session.setAttribute("username", "admin"); // 向session中设置属性
 5         session.setAttribute("password", "123456");
 6         session.setAttribute("age", 16);
 7   %>
 8 
 9  <%
10   //获取session中保存的属性
11   String[]names=session.getValueNames();
12       if(names!=null){
13           for(String str:names){
14               out.print(str+"\\t");
15           }
16       }
17    %>
复制代码

  Session的生命周期:

  • 创建:当客户端第一次访问某个jsp页面或者Servlet的时候,服务器会为当前会话创建一个SessionId。每次客户端向服务器发送请求的时候都会携带此SessionId,服务端会对此SessionId进行检验——判断是否属于同一次会话。
  • 活动阶段:某次会话中通过超链接打开新的页面;只要当前页面没有全部关闭,打开新的浏览器窗口访问同一项目资源也属于同一会话。注意:原有的会话仍然存在,只不过再也没有客户端会携带此sessionId交给服务器检验。——创建一个新的会话并不意味着原有会话消失,除非超时。
  • 销毁。

  Tomcat如何进入后台管理系统?

   修改/conf/tomcat-user.xml为以下:

1 <?xml version="1.0" encoding="UTF-8"?>
2 <tomcat-users>
3   <role rolename="admin-gui"/>
4   <role rolename="manager-gui"/>
5   <user username="admin" password="admin" roles="admin-gui,manager-gui"></user>
6 </tomcat-users>

  在浏览器中打开session_page1.jsp然后通过session_page1.jsp的超链接打开session_page2.jsp在后台管理系统中查看:

 

  如果我们在session创建之后调用session.invalidate()方法,例如:我们在session_page1.jsp中这样写:

复制代码
 1  <h1>session内置对象</h1>
 2     <h2>session_page1.jsp</h2>
 3     <%
 4         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
 5         String date = sdf.format(new Date(session.getCreationTime()));
 6         out.print("session的创建时间:" + date);
 7         
10         session.setAttribute("username", "admin"); // 向session中设置属性
11         session.setAttribute("password", "123456");
12         session.setAttribute("age", 16);
13      %>
14    <br />Session的ID号:<%=session.getId() %><hr />
15   session中保存的属性有:<br />
16   <%
17   //获取session中保存的属性
18   String[]names=session.getValueNames();
19       if(names!=null){
20           for(String str:names){
21               out.print(str+"\\t");
22           }
23       }
24       session.invalidate();//销毁session
25    %>
26    <a href = "session_page2.jsp" target = "_blank">点击在新标签页中打开session_page2.jsp</a>
复制代码

  运行结果(不断刷新浏览器):

  Session默认session超时是30min设置session对象的超时有两种方式:

  • session.setMaxInactiveInterval(5);单位是秒
  • 在web.xml中配置(单位是分钟):
  • <session-config>
            <session-timeout>30</session-timeout>
    </session-config>

    3.9application对象

  • application对象实现了用户间数据的共享,可以存放全局变量。
  • application对象开始于服务器的启动,结束于服务器的关闭。
  • 在用户的前后连接或者不同用户之间,可以对统一个application对象的属性进行操作。
  • 在任何地方对application对象属性的操作将会影响到其他用户对此的访问。
  • application对象是ServletContext类的实例。
  • 该对象的常用方法如下:
1 void setAttribute(String name,Object value); // 指定名称将对象绑定到此会话
2 Object getAttribute(String name);            // 返回此会话中和指定名称绑定在一起的对象,如果没有对象绑定在该名称下则返回null
3 Enumeration getAttributeNames();             // 返回所有可用属性名的枚举
4 String getServerInfo();                      // 返回JSP(Servlet)引擎名和版本号

  

复制代码
 1     <h1>application对象</h1>
 2     <%
 3         //在application中保存3个键值对
 4         application.setAttribute("city", "北京");
 5         application.setAttribute("zipcode", "10000");
 6         application.setAttribute("email", "io@gmail.com");
 7      %>
 8      所在城市:<%=application.getAttribute("city") %><hr>
 9      application中存放的属性有:<br>
10      <%
11          Enumeration attrs = application.getAttributeNames();
12          while(attrs.hasMoreElements()){
13              out.print(attrs.nextElement()+"<br>");
14          }
15       %>
16       <hr>
17       jsp(Servlet)引擎:<%=application.getServerInfo() %><br>
复制代码

  运行效果:

  3.10page对象

    page对象就是指向当前jsp页面本身(就好像类中的this),是java.lang.Object类的实例,常用方法和Object类的方法一致。例如它的toString()方法:

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

  运行结果:

  我们打开tomcat的work目录(编译生成的Servlet目录)看到它的包结构是org.apache.jsp,在该目录下有一系列的*_jsp.java和*_jsp.class文件。我们打开page_jsp.java发现类名就是page_jsp。

  3.11pageContext对象

  • 提供了对JSP页面内所有的对象及名字空间的访问。
  • 可以访问到本页所在的session,也可以取本页面所在的application的某一属性值
  • 相当于页面中所有功能的集大成者。
  • pageContext对象的本类名也叫pageContext。
  • 常用方法:
复制代码
1 JspWriter getOut();                           // 返回当前客户端响应被使用的JspWriter流(out)
2 HttpSession getSession();                     // 返回当前页中的HttpSession对象(session)
3 Object getPage();                             // 返回当前页面的Object对象(page)
4 ServletRequest getRequest();                  // 返回当前页面的ServletRequest对象(request)
5 ServletResponse getResponse();                // 返回当前页面的ServletResponse对象(response)
6 void setAttribute(String name,Object value);  // 设置属性键值对
7 Object getAttribute(String name,int scope);   // 在指定范围内取属性值
8 void forward(String relativeUrlPath);         // 将当前页面重定向到另一页面
9 void include(String relativeUrlPath);         //  在当前页面包含另一文件
复制代码

  我们在session_page1.jsp中向session中设置了用户名:

<%
    session.setAttribute("username", "admin");
%>

  现在我们在pageContext.jsp中取出session中存储的用户名(注意要先打开session_page1.jsp):

<h1>pageContext内置对象</h1>
    用户名:<%=pageContext.getSession().getAttribute("username") %>

  运行结果:

  用pageContext实现页面跳转:

  <%
        pageContext.forward("reg.jsp");
  %>

  运行结果:

    新建一个include.jsp(页面用于向页面输出当前的日期):

1 <%@page import="java.text.SimpleDateFormat"%>
2 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
3 <%
4     out.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
5 %>

  下面我们在pageContext.jsp页面中包含include.jsp:

1    <h1>pageContext内置对象</h1>
2     用户名:<%=pageContext.getSession().getAttribute("username") %><hr>
3     
4     <!-- 包含其他页面 -->
5     <%pageContext.include("include.jsp"); %>

  3.12config对象

      该对象是一个在servlet初始化时,jsp引擎向它传递信息时使用的,此信息包含Servlet初始化时所用到的参数(键-值对)以及服务器的相关信息(通过传递一个ServletContext对象),常用方法:

1 ServletContext getServletContext();  // 返回服务器相关信息的ServletContext对象
2 String getInitParameter(String name);// 返回初始化参数的值
3 Enumeration getInitParameterNames(); // 返回Servlet初始化时所有需要参数的枚举

  3.13exception对象

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

1 String getMessage();            // 返回异常的描述信息
2 String toString();              // 返回关于异常的简短描述信息
3 void printStackTrace();         // 显示异常及其栈轨迹
4 Throwable FillInStackTrace();   // 重写异常的执行栈轨迹

  首先建立一个会出现异常的页面exception_text.jsp(并指定处理异常的页面):

复制代码
 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8" errorPage="exception.jsp"%>
 2 <!-- 在errorPage中指定处理异常的页面 -->
 3 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 4 <html>
 5   <head>
 6     <title>这个页面肯定会出现异常</title>
 7   </head>
 8   
 9   <body>
10     <h1>测试异常对象</h1><hr />
11     <%
12            out.println(100/0);//肯定会抛出运行时异常【算术异常】
13      %>
14   </body>
15 </html>
复制代码

  然后建立处理异常的页面exception.jsp: