jsp主板 jtp_java web学习笔记-jsp篇

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

2

3

4

5

手工编写的第一个java web项目

6

7

8

这是手工编写的第一个java web项目——jsp

9


10

11

在项目目录中创建一个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

2 /haha.jsp

3

运行结果:

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的以下标记:

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指令语法:

属性

描述

默认值

language

jsp页面所使用的脚本语言

java

import

引用脚本语言中所要使用的类文件

contentType

指定jsp页面的编码

text/html,ISO-8859-1

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

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

这样就支持中文了。

page指令的全部属性如下:

1

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

2.4jsp注释

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

1

2

3

4 /*这里是jsp脚本注释 有两种*/

5

6 //单行注释7

8 /*多行注释*/

9 %>

例如:

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

12

My JSP 'index.jsp' starting page

13

14

15

16

17

18

21

22

23

24

欢迎你

25

26

27

28 /*这里是jsp脚本注释29 有两种*/

30 //单行注释31 /*多行注释*/

32 %>

33

34

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

2.5jsp脚本

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

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

12

My JSP 'index.jsp' starting page

13

14

15

16

17

18

21

22

23

24

欢迎你

25


26

27 out.println("通过jsp内置对象out对象打印输出");28 %>

29

30

2.6jsp声明

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

例如:

1

2.7jsp表达式

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

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

12

My JSP 'index.jsp' starting page

13

14

15

16

17

18

21

22

23

24

欢迎你

25


26

27

33 你好:

34 令x=10,y=5,则x+y =

35

36

运行结果:

2.8jsp页面生命周期

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

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

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

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

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

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

1

2

3 contentType="text/html; charset=utf-8"%>

4

5 Stringpath=request.getContextPath();6 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";7 %>

8

9

10

11

12 ">

13

14

My JSP 'multiplicationTable.jsp' starting page

15

16

17

18

19

20

21

22

23

24

25

26

九九乘法表

27

表达式的方式打印乘法表

28 ");//追加换行标记,注意不能使用\n37 }38 return s.toString();39 }40 %>

41

43

44

使用脚本的方式打印九九乘法表

45 ");54 }55 out.println(s.toString());56 }57 %>

58

59

60 //调用脚本61 printMultiTable2(out);62 %>

63

64

运行结果:

3.jsp内置对象

3.1jsp内置对象简介

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

1 ");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

JSP的out内置对象

2

3 //jsp脚本4 out.println("

静夜思

");5 out.println("李白
");6 out.println("窗前明月光,
");7 out.println("疑是地上霜。
");8 out.println("举头望明月,
");9 out.println("低头思故乡。
");10 %>

11

12 缓冲区大小:字节。

13 剩余缓冲区(可用缓冲区):字节。

14 是否自动清空缓冲区:

运行结果:

1

JSP的out内置对象

2

3 //jsp脚本4 out.println("

静夜思

");5 out.println("李白
");6 out.println("窗前明月光,
");7 out.flush();//将缓冲区中的内容输出到客户端8 out.println("疑是地上霜。
");9 out.println("举头望明月,
");10 out.println("低头思故乡。
");11 %>

12

13 缓冲区大小:字节。

14 剩余缓冲区(可用缓冲区):字节。

15 是否自动清空缓冲区:

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

1

2 //jsp脚本3 out.println("

静夜思

");4 out.println("李白
");5 out.println("窗前明月光,
");6

7 out.flush();//将缓冲区中的内容输出到客户端8 out.clear();//在flush之后调用clear,将会抛出异常9

10 out.println("疑是地上霜。
");11 out.println("举头望明月,
");12 out.println("低头思故乡。


");13 %>

运行结果:

1

2 //jsp脚本3 out.println("

静夜思

");4 out.println("李白
");5 out.println("窗前明月光,
");6

7 out.flush();//将缓冲区中的内容输出到客户端8 out.clearBuffer();//在flush之后调用clearBuffer不会抛出异常9

10 out.println("疑是地上霜。
");11 out.println("举头望明月,
");12 out.println("低头思故乡。


");13 %>

运行结果:

3.4post和get提交方式的区别

get:以明文的方式通过URL提交数据,提交的数据最大不超过2K。适合提交数据量小,安全性不高的数据【例如:搜索和查询】

post:将用户提交的数据封装在URL HEADER内。适合提交数据量大,安全性高的数据【例如:注册、修改、上传】

下面以用户登录的例子比较两者的区别:

login.jsp页面

1 请输入用户名和密码:2

3 用户名:

4 密码:

5

6

处理登录的动作脚本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 请输入相关信息完成注册

2

3 用户名:

4 密码:

5 爱好:6 读书7 音乐8 电影9 上网

10

11

处理用户注册页的request.jsp

1

request内置对象

2

3 用户名:

4 密码:


5 爱好:

6

7 String[]favorites=request.getParameterValues("favorite");8 for(Stringstr:favorites){ 9 out.print(str+"  ");10 }11 %>

运行结果:

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

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

1

request内置对象

2

3

4 用户名:

5 密码:


6 爱好:

7

8 String[]favorites=request.getParameterValues("favorite");9 for(Stringstr:favorites){10 out.print(str+"  ");11 }12 %>

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

reg.jsp

测试URL传参

request.jsp(不变)

1

request内置对象

2

3

4 用户名:

5 密码:


6 爱好:

7

8 String[]favorites;9 if((favorites=request.getParameterValues("favorite"))!=null){10 for(Stringstr:favorites){11 out.print(str+"  ");12 }13 }14 %>

运行结果:

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

测试URL传参

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

向request对象中添加键值对:

reg.jsp:

1   请输入相关信息完成注册

2

3 用户名:

4   密码:

5 爱好:6 读书7 音乐8 电影9 上网

10

11

request.jsp

1

request内置对象

2

3

4

5 //在request对象中保存一个email属性6 request.setAttribute("email","io@gmail.com");7

8 %>

9 用户名:

10 密码:


11 爱好:

12

13 String[]favorites;14 if((favorites=request.getParameterValues("favorite"))!=null){15 for(Stringstr:favorites){16 out.print(str+"  ");17 }18 }19 %>

20
邮箱:

运行结果:

1

request内置对象

2

3

4

5 //在request对象中保存一个email属性6 request.setAttribute("email","io@gmail.com");7

8 %>

9 用户名:

10 密码:


11 爱好:

12

13 String[]favorites;14 if((favorites=request.getParameterValues("favorite"))!=null){15 for(Stringstr:favorites){16 out.print(str+"  ");17 }18 }19 %>

20
邮箱:


21 请求体的MIME类型:

22 请求体的协议及版本号:

23 服务器主机名:

24 服务器端口号:

25 请求的字符编码:

26 请求的文件长度:字节

27 请求的客户端的IP:

28 请求的真实路径:

29 请求的上下文路径:

运行结果:

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

2

3

4 response.setContentType("text/html;charset=utf-8");//设置响应的MIME类型5

6 out.println("

response内置对象


");7

8 PrintWriter outer=response.getWriter();//获得输出流对象9 outer.println("我是response对象生成的outter对象,在页面中总是在前面输出");10 %>

运行结果:

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

请求重定向——当用户请求response.jsp的时候马上跳转到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

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   

session内置对象

2

session_page1.jsp

3

4 SimpleDateFormat sdf= newSimpleDateFormat("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
Session的ID号:

10 从session中获取用户名:

11

12 以新窗口的方式打开session_page2.jsp

session_page2.jsp

1

session_page2.jsp

2

3 SimpleDateFormat sdf= newSimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");4 String date =sdf.format(new Date(session.getCreationTime()));5 out.print("session的创建时间:" + date);6 %>

7
Session的ID号:

8 从session中获取用户名:

运行结果:

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

1

2 session.setMaxInactiveInterval(5);//设置session的有效期为5s3

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(Stringstr: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

3

4

5

6

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

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

1

session内置对象

2

session_page1.jsp

3

4 SimpleDateFormat sdf= newSimpleDateFormat("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
Session的ID号:


15 session中保存的属性有:

16

17 //获取session中保存的属性18 String[]names=session.getValueNames();19 if(names!=null){20 for(Stringstr:names){21 out.print(str+"\t");22 }23 }24 session.invalidate();//销毁session25 %>

26 点击在新标签页中打开session_page2.jsp

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

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

session.setMaxInactiveInterval(5);单位是秒

在web.xml中配置(单位是分钟):

30

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

application对象

2

3 //在application中保存3个键值对4 application.setAttribute("city","北京");5 application.setAttribute("zipcode","10000");6 application.setAttribute("email","io@gmail.com");7 %>

8 所在城市:


9 application中存放的属性有:

10

11 Enumeration attrs=application.getAttributeNames();12 while(attrs.hasMoreElements()){13 out.print(attrs.nextElement()+"
");14 }15 %>

16


17 jsp(Servlet)引擎:

运行效果:

3.10page对象

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

1

page内置对象

2 当前页面的page对象的字符串描述:

3

运行结果:

我们打开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中设置了用户名:

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

pageContext内置对象

用户名:

运行结果:

用pageContext实现页面跳转:

运行结果:

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

1

2

3

4 out.print(newSimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));5 %>

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

1

pageContext内置对象

2 用户名:


3

4

5

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

2

3

4

5

6

这个页面肯定会出现异常

7

8

9

10

测试异常对象


11

12 out.println(100/0);//肯定会抛出运行时异常【算术异常】13 %>

14

15

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

My JSP 'exception.jsp' starting page

Exception内置对象

异常消息是:
异常的字符串描述:

运行结果:

3.14阶段案例——实现用户登录

这个案例比较简单:用户名和密码都是admin(没有使用数据库),如果用户名和密码相符,则页面跳转到login_success.jsp【服务器内部转发】,提示用户登录成功;如果用户登录失败,则页面跳转到login_failure.jsp【请求重定向】,提示用户登录失败。

整个项目的截图:

4.java beans

JavaBean是使用Java语言开发的一个可重用的组件,在JSP的开发中可以使用JavaBean减少重复的代码,使整个JSP代码的开发更加简洁。JSP配置JavaBean使用有以下优点:

1. 将html和java大妈分离,为日后的维护提供了方便。

2. 可以利用JavaBean的优点将常用到的程序写成JavaBean组件,节省开发时间。

简单JavaBean有以下几个名词:

VO:值对象,存放所有的传递数据的操作上

POJO:简单java对象

TO:传输对象,必须实现Serializable接口

WEB开发的标准目录结构

实际上在WEB-INF中的lib和classes目录就相当于一个默认的classpath(类执行时所需要的一个重要的环境属性)。当Tomcat启动之后,WEB-INF/lib和WEB-INF/classes都会自动配置到classpath中。

4.1java bean简介与设计原则

Javabeans就是符合某种特定规范的的Java类。它的好处有:

一个Javabean要满足4个规范:

例如以下的学生类就是一个Javabean:

1 /**

2 * 这是一个典型的JavaBean3 */

4

5 //1.这是一个共有的类

6 public classStudent {7 //2.属性私有

8 privateString name;9 private intage;10

11 //3.有共有的无参构造

12 publicStudent() {13 }14

15 //4.getter和setter

16 publicString getName() {17 returnname;18 }19

20 public voidsetName(String name) {21 this.name =name;22 }23

24 public intgetAge() {25 returnage;26 }27

28 public void setAge(intage) {29 this.age =age;30 }31

32 }

JavaBean有2种应用方式:

4.2jsp动作元素【运行时】

JSP动作元素(action elements),动作元素为请求处理阶段提供信息。动作元素遵循XML元素的语法——有一个元素名的开始标签,可以有属性、可选的内容、与开始标签匹配的结束标签。

4.3普通方式应用java bean

像使用普通java类一样,创建javabean实例。在MyEclipse项目的src目录下新建类Users:

1 packageorg.po;2

3 /**

4 * 用户类-符合Javabean的实际原则5 */

6 public classUsers {7 privateString username;8 privateString password;9

10 publicUsers() {11

12 }13

14 publicString getUsername() {15 returnusername;16 }17

18 public voidsetUsername(String username) {19 this.username =username;20 }21

22 publicString getPassword() {23 returnpassword;24 }25

26 public voidsetPassword(String password) {27 this.password =password;28 }29

30 }

下面我们在javabean_page1.jsp中使用以上的Javabean:

1

2

3

4

5

6

7

8

JavaBeans范例

9

10

11

12

使用普通方式创建Javabean的实例

13

14 //使用普通方式创建JavaBean15 Users user= newUsers();16 user.setUsername("admin");17 user.setPassword("admin");18 %>

19 用户名:

20 密码:

21

22

运行结果:

4.4useBean动作元素

用于在jsp页面中实例化或者在指定范围内使用JavaBean。基本操作是首先使用id和作用域查找一个现有的对象,如果在指定的作用域中没有找到具有指定id的对象,那么它会试图使用其他属性创建一个新实例。语法如下:

1

2

3

4

5

6

使用useBean动作指令来使用JavaBean

7

8

9

10

使用<jsp:useBean>动作指令来使用JavaBean

11

12

13 用户名:

14 密码:

15

16

运行结果:

4.5setProperty

上一个jsp页面中取得的用户名和密码都为null,原因就是我们使用仅仅是实例化了Users对象,并没有为其成员变量执行属性。当然你也可以使用setXXX来给已经实例化的JavaBean设置属性,不过我更推荐使用setProperty指令。

的主要作用就是给已经实例化的JavaBean的属性赋值,一共有4种形式:

1                       

2                

3     

4

方式一:【表单内容的自动全部匹配】

新建一个用户登录表单login.jsp:

1

2 用户名:

3 密码:

4   

5

处理用户登录的页面dologin.jsp

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

用户登录处理页面

12

13

14

15

16

17

18

19

setPerpority动作元素


20

21

22

23 用户名:

24 密码:

25

26

27

运行结果:

这实际上以依靠表单中的name属性来匹配javabean中的成员变量。例如:在用户登录表单中input标记的属性有一个name="username",那么使用这种自动匹配的方式就会把这个username与javabean中的属性挨个查找,如果找到了就为这个字段设定相应的值——换言之:表单中的name属性要和要和javabean中的属性对应相同。

方式二:部分匹配表单的属性(dologin.jsp):

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

用户登录处理页面

12

13

14

15

16

17

18

19

setPerpority动作元素


20

21

22

23 用户名:

24 密码:

25

26

27

运行结果:

仅仅匹配了用户名属性,由于密码属性没有匹配,所以为null。这种方式也要注意表单的name属性要和javabean的属性相同。

方式三:手工给javabean的属性赋值——与表单无关(dologin.jsp):

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

用户登录处理页面

12

13

14

15

16

17

18

19

setPerpority动作元素


20

21

22

23

24 用户名:

25 密码:

26

27

28

方式四(通过URL传参的方式给javabean赋值):

login.jsp:

通过url传参的方式给javabean的属性赋值

dologin.jsp:

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

用户登录处理页面

12

13

14

15

16

17

18

19

setPerpority动作元素


20

21

22

23

24 用户名:

25 密码:

26

27

28

运行结果:

4.6getProperty

获取指定JavaBean对象的属性值【String类型】。语法:

前面的例子已经通过URL传递参数的方式指定了javabean的属性值,现在通过getProperty的方式获得javabean的属性值:

1

2

3 Stringpath=request.getContextPath();4 StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";5 %>

6

7

8

9

10 ">

11

用户登录处理页面

12

13

14

15

16

17

18

19

setPerpority动作元素


20

21

22

23

24

25

26

27 用户名:

28 密码:

29 --%>30

31

32 用户名:

33 密码:

34

35

运行结果:

4.7java bean的4个作用域范围

使用useBean的scope属性可以指定javabean的作用域。

1 page //当前页面有效,可以通过PageContext.getAttribute()获得JavaBean对象。

2 request //同一个请求有效,可通过HttpRequest.getAttibute()方法获得JavaBean对象。

3 session //同一个session有效,可通过HttpSession.getAttribute()方法获得JavaBean对象。

4 application //同一个application有效,可通过application.getAttribute()方法获得JavaBean对象。

下面是一个简单的测试4个作用范围的示例:

dolog.jsp以URL传参的方式为javabean指定属性值:

1

2

3

4

5

用户登录处理页面

6

7

8

9

10

11

12

13

setPerpority动作元素


14

15

16

17

18

19 测试javabean的4个作用域范围

20

21

22

dologin.jsp中有一个跳转链接test_scope.jsp用于跳转页面,下面是test_scope.jsp。

1

2

3

4

5

6

7

检验useBean的4个作用域

8

9

10

11

检验useBean的4个作用域


12

13

14

15

用jsp动作元素获取javabean的属性值

16 用户名:

17 密码:


18

19

20

通过内置对象获取javabean的属性值

21 用户名:

22 密码:

23

24

按照上面的例子分别将scope换成session、request和page得到如下如下结果:javabean的作用域范围从大到小依次是:application、session、request、page。

4.8JavaBean的删除

JavaBean虽然使用了标签进行创建,但是其操作仍然依靠的是4种属性范围。如果一个JavaBean不再使用的话,则可以使用对应的removeAttribute()方法进行删除。

1 pageContext.removeAttribute(JavaBean名称) //删除page范围内的JavaBean

2 request.removeAttribute(JavaBean名称) //删除request范围内的JavaBean

3 session.removeAttribute(JavaBean名称) //删除session范围内的JavaBean

4 application.removeAttribute(JavaBean名称) //删除application范围内的JavaBean

1 packageorg.gpf;2

3 public classCount {4

5 private int count = 0;6

7 publicCount() {8 System.out.println("======== 一个新的Count实例产生了 ========");9 }10

11 public intgetCount() {12 return ++count;13 }14

15 }

Count.java

1

2

3

4 count =

5

6 session.removeAttribute("c");//删除javaBean7 %>

session_bean.jsp

我们本来设置的是session范围内的JavaBean,刷新页面不应该有新的JavaBean产生,但是我们在最后使用了session.removeAttribute()方法将创建的JavaBean删除了,因而每次请求都会产生新的JavaBean。

4.9model 1(JSP+JavaBean)简介

Model 1模型出现以前,整个Web应用几乎全部由JSP页面组成,JSP页面接收处理客户端请求,对请求处理后直接响应。这样做的一个弊端就是:在界面层(JSP页面)中充斥着大量的业务逻辑代码和数据访问层的代码,Web程序的可扩展性和可维护性非常差。

JavaBean的出现可以使得可以在JSP页面中调用JavaBean封装的数据或者业务逻辑代码,大大提升了程序的可维护性。下面的这张图简单描述了Model 1.

模型一体现了一种Web应用的分层架构。

4.9阶段项目(使用Model 1完成用户登录)

首先建立一个用户类Users(javabean):

1 packageorg.po;2

3 /**

4 * 用户类-javabean5 */

6 public classUsers {7 privateString username;8 privateString passwordString;9

10 publicUsers() {11 }12

13 publicString getUsername() {14 returnusername;15 }16

17 public voidsetUsername(String username) {18 this.username =username;19 }20

21 publicString getPasswordString() {22 returnpasswordString;23 }24

25 public voidsetPasswordString(String passwordString) {26 this.passwordString =passwordString;27 }28

29 }

下面编写一个用户业务逻辑类:

1 packageorg.dao;2

3 importorg.po.Users;4

5 /**

6 * 用户的业务逻辑类7 */

8 public classUsersDAO {9 public booleanisUserLogin(Users users) {10 return "admin".equals(users.getUsername())11 && "admin".equals(users.getPassword());12 }13 }

业务逻辑处理的页面dologin.jsp:

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

7

8

9

10

11

12

13 request.setCharacterEncoding("utf-8");//防止中文乱码

14 if(userDAO.isUserLogin(loginUser)){15 //如果用户登录成功则向session中设置用户名和密码

16 session.setAttribute("username", loginUser.getUsername());17 session.setAttribute("password", loginUser.getPassword());18 //请求转发

19 request.getRequestDispatcher("login_success.jsp").forward(request, response);20 }else{21 //重定向

22 response.sendRedirect("login_failure.jsp");23 }24 %>

该项目中主要的修改的dologin.jsp在该页面中没有使用request对象直接从表单中读出数据,而是从javabean中取出属性,并且用户合法性的判断也放在了javabean中很好的体现了Web的分层思想(逻辑与页面分离)。

5.jsp状态管理

5.1http协议的无状态性

http的无状态性是指:当浏览器发送请求给服务器的时候,服务器响应客户端的请求。但是当浏览器再次发送请求给服务器的时候,服务器并不知道它就是刚刚的那个浏览器。——服务器不会记住你。为了保存用户的状态有两种机制:

5.2Cookie

Cookie是Web服务器保存在客户端的一系列文本信息。

Cookie的典型应用一:判断注册用户是否已经登录网站。保存用户的登录状态,简化登录的手续(记住密码)。

Cookie的典型应用二:“购物车”的处理。

Cookie的典型应用三:视频网站播放记录的存储。

在JSP页面中创建和使用Cookie

1 Cookie newCookie = new Cookie(String key,Object value); //创建Cookie对象

2 response.add(newCookie); //写入Cookie对象

3 Cookie[] cookies = request.getCookies(); //读取Cookie对象

Cooike对象的常用方法:

1 void setMaxAge(int expiry); //设置cookie的有效期【秒】

2 void setValue(String value);//对已经实例化的cookie对象赋值

3 String getName(); //获得cookie的名称

4 String getValue(); //获得cookie的值

5 int getMaxAge(); //获得cookie的有效时间【秒】

注意:以上方法中的setValue(String value)和String getValue()方法的返回值都是字符串类型——因为Cookie本质上就是一个字符串存储在客户端,无论对它存值还是取值都应该是字符串类型。

5.3案例:Cookie在登录中的应用:

实现记忆用户名和密码的功能。

用户登陆页login.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

用户登录

7

8

9

10

11 /*获得Cookie中保存的用户名和密码*/

12 Stringusername= "";13 Stringpassword= "";14

15 Cookie[]cookies=request.getCookies();16 if(cookies!=null&&cookies.length>0){17 for(Cookie c:cookies){18 if(c.getName().equals("username")){19 username=c.getValue();20 }21 if(c.getName().equals("password")){22 password=c.getValue();23 }24 }25 }26 %>

27

28 请输入用户名和密码:29

30

31 用户名:" />

32 密码:">

33

34 十天内记住我

35

36

37

38

处理用户登录的页面dologin.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

处理用户登录

7

8

9

10

登录成功!

11


12

13 //判断用户是否选择了记住密码14 String[] isUseCookie=request.getParameterValues("isUseCookie");15 if(isUseCookie!=null&&isUseCookie.length>0){16 /*把用户名和密码保存在Cookie对象中*/

17 Stringusername=request.getParameter("username");18 Stringpassword=request.getParameter("password");19 //创建2个Cookie对象20 Cookie usernameCookie= newCookie("username",username);21 Cookie passwordCookie= newCookie("password",password);22 usernameCookie.setMaxAge(3600*24*10);//设置cookie生存期10天23 passwordCookie.setMaxAge(3600*24*10);24

25 //在客户端保存Cookie对象,需要依赖response对象的addCookie方法26 response.addCookie(usernameCookie);27 response.addCookie(passwordCookie);28 }else{29 /*使已经保存的cookie对象失效*/

30 Cookie[]cookies=request.getCookies();//得到客户端保存的cookie31 if(cookies!=null&&cookies.length>0){32 //遍历Cookie数组33 for(Cookie c:cookies){34 if(c.getName().equals("username")||c.getName().equals("password")){35 c.setMaxAge(0);//设置Cookie的有效期是0,让其马上失效36 response.addCookie(c);//重新向客户端保存Cookie37 }38 }39 }40 }41 %>

42 点击查看用户信息

43

44

用户信息显示页users.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

用户信息显示

7

8

9

10

用户信息

11


12

13 /*获得Cookie中保存的用户名和密码*/

14 Stringusername= "";15 Stringpassword= "";16

17 Cookie[]cookies=request.getCookies();18 if(cookies!=null&&cookies.length>0){19 for(Cookie c:cookies){20 if(c.getName().equals("username")){21 username=c.getValue();22 }23 if(c.getName().equals("password")){24 password=c.getValue();25 }26 }27 }28 %>

29 用户名:
密码:

30

31

该项目一般情况下能够正常运行,但是当我们输入中文用户名的时候,服务器会抛出一个500的错误。要解决这个问题就需要依靠java网络包中的URLEncoder和URLDecoder,除此之外不要忘记了在每次使用request对象之前首先要设置request对象的编码方式。完整的代码如下:

login.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

7

用户登录

8

9

10

11

12 /*获得Cookie中保存的用户名和密码*/

13 Stringusername= "";14 Stringpassword= "";15

16 request.setCharacterEncoding("utf-8");17 Cookie[]cookies=request.getCookies();18 if(cookies!=null&&cookies.length>0){19 for(Cookie c:cookies){20 if(c.getName().equals("username")) {21 username=URLDecoder.decode(c.getValue(),"utf-8");22 }23 if(c.getName().equals("password")) {24 password=URLDecoder.decode(c.getValue(),"utf-8");25 }26 }27 }28 %>

29

30 请输入用户名和密码:31

32

33 用户名:" />

34 密码:">

35

36 十天内记住我

37

38

39

40

dologin.jsp

1

2

3 contentType="text/html; charset=utf-8"%>

4

5

6

7

处理用户登录

8

9

10

11

登录成功!

12


13

14 //判断用户是否选择了记住密码15 request.setCharacterEncoding("utf-8");16 String[] isUseCookie=request.getParameterValues("isUseCookie");17 if(isUseCookie != null &&isUseCookie.length> 0) {18 /*把用户名和密码保存在Cookie对象中*/

19 //得到登录表单中的内容并编码20 Stringusername=URLEncoder.encode(21 request.getParameter("username"),"utf-8");22 Stringpassword=URLEncoder.encode(23 request.getParameter("password"),"utf-8");24 //创建2个Cookie对象25 Cookie usernameCookie= newCookie("username", username);26 Cookie passwordCookie= newCookie("password", password);27 usernameCookie.setMaxAge(3600 * 24 * 10);//设置cookie生存期10天28 passwordCookie.setMaxAge(3600 * 24 * 10);29

30 //在客户端保存Cookie对象,需要依赖response对象的addCookie方法31 response.addCookie(usernameCookie);32 response.addCookie(passwordCookie);33 }else{34 /*使已经保存的cookie对象失效*/

35 Cookie[] cookies=request.getCookies();//得到客户端保存的cookie36 if(cookies != null &&cookies.length> 0) {37 //遍历Cookie数组38 for(Cookie c : cookies) {39 if(c.getName().equals("username")40 || c.getName().equals("password")) {41 c.setMaxAge(0);//设置Cookie的有效期是0,让其马上失效42 response.addCookie(c);//重新向客户端保存Cookie43 }44 }45 }46 }47 %>

48 点击查看用户信息

49

50

users.jsp

1

2

3 contentType="text/html; charset=utf-8"%>

4

5

6

7

用户信息显示

8

9

10

11

用户信息

12


13

14 /*获得Cookie中保存的用户名和密码*/

15 Stringusername= "";16 Stringpassword= "";17

18 request.setCharacterEncoding("utf-8");19 Cookie[] cookies=request.getCookies();20 if(cookies != null &&cookies.length> 0) {21 for(Cookie c : cookies) {22 if(c.getName().equals("username")) {23 username=URLDecoder.decode(c.getValue(),"utf-8");24 }25 if(c.getName().equals("password")) {26 password=URLDecoder.decode(c.getValue(),"utf-8");27 }28 }29 }30 %>

31 用户名:
密码:

32

33

修正后的项目就支持中文用户名了。Cookie与Session的区别是Cookie存放于浏览器中,浏览器关闭后再打开,已经保存的cookie还是存在。

5.4Session与Cookie对比

Session

Cookie

保存位置

服务端保存用户信息

客户端保存用户信息

保存类型

Session中保存的是Object类型

Cookie中保存的是String类型

生命周期

会话结束,则存储的数据销毁

Cookie可长期保存在客户端

重要性

保存重要信息

保存不重要信息

6.jsp指令【编译时】与动作【运行时】元素

6.1include指令(可以包含其他页面)

语法:

例如我们要在include_command.jsp中包含date.jsp的页面——即:在include_command中显示date.jsp的内容:

date.jsp

1

2

3

4 out.print(newSimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));5 %>

include_command.jsp

1

2

3

4

5

在该页面中使用include指令将刚刚写的date.jsp包含进来

6

7

8

9

在该页面中使用include指令将刚刚写的date.jsp包含进来


10

11

12

运行结果:

6.2include动作

include动作实际上是JSP动作标签,语法:

其中page属性是需要包含的页面的URL,而flush属性制定了被包含的页面是否从缓冲区中读取。

demo:使用include动作在include_action.jsp中包含date.jsp

include_action.jsp

1

2

3

4

5

include动作

6

7

8

9

在该页面中使用include动作将刚刚写的date.jsp包含进来


10

11

12

使用include动作和include指令在jsp页面的执行效果上没有任何区别。

6.3include指令与include动作的区别

在Tomcat服务器的work目录中删除刚刚发布的工程:

先访问include_command.jsp

work目录生成以下内容:

打开include_005fcommand_jsp.java发现在它的源代码中有date.jsp的源代码:

out.print(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));

include指令主页面和被包含的页面转换成了同一个Servlet。

在Tomcat的work目录中删除编译生成的Servlet,访问include_action.jsp生成以下文件:

打开include_005faction_jsp.java发现源代码中并没有包含date.jsp的源代码,而是由下面的一条代码将date.jsp的输出结果包含到该jsp页面:

//该语句相当于调用date.jsp,并将date.jsp的输出结果返回给该页面

org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "date.jsp", out, false);

6.4forward动作

服务器内部转发指令,语法:

1

2

3 //相当于

4 request.getRequestDispatcher("url").forward(request,response);

例如:在登陆页中将用户的表单处理交给forward_action.jsp页面处理,forward_action.jsp将该请求通过forward动作转发给users.jsp,users.jsp从request对象中取得用户名和密码给予显示:

login.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

用户登录

7

8

9

10 请输入用户名和密码:11

12

13 用户名:

14 密码:

15

16

17

18

forward_action.jsp

1

2

3

4

5

forward动作

6

7

8

9

该页面处理用户提交的表单信息

10

forward动作

11

12

13

14 request.getRequestDispatcher("users.jsp").forward(request, response);15 --%>

16

17

users.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

用户信息显示

7

8

9

10

用户信息

11


12

13 request.setCharacterEncoding("utf-8");14

15 Stringusername= "";16 Stringpassword= "";17 if(request.getParameter("username")!=null){18 username=request.getParameter("username");19 }20 if(request.getParameter("password")!=null){21 password=request.getParameter("password");22 }23 %>

24 用户名:
密码:

25

26

运行结果:

6.5param动作

语法:

1

2

用户将提交的表单交给dologin.jsp处理,dologin.jsp通过forward动作把请求转发给users.jsp(并人为添加表单中没有的内容:邮箱,修改表单中提交的用户名为root),users.jsp通过request.getParamer()方法获得用户名、密码、邮箱并予以显示:

login.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

用户登录

7

8

9

10 请输入用户名和密码:11

12

13 用户名:

14 密码:

15

16

17

18

dologin.jsp

1

2

3

4

5

users.jsp

1

2 contentType="text/html; charset=utf-8"%>

3

4

5

6

用户信息显示

7

8

9

10

用户信息

11


12

13 request.setCharacterEncoding("utf-8");14

15 Stringusername= "";16 Stringpassword= "";17 Stringemail= "";18 if(request.getParameter("username")!=null){19 username=request.getParameter("username");20 }21 if(request.getParameter("password")!=null){22 password=request.getParameter("password");23 }24 if(request.getParameter("email")!=null){25 email=request.getParameter("email");26 }27 %>

28 用户名:
密码:
邮箱:

29

30

效果图:

7.jsp案例项目——商品浏览记录的实现

该项目使用Model1(JSP+JavaBean)使用Cookie机制实现。该项目使用到了数据库(数据库中存放了商品表)。实现步骤如下:

DB-->JavaBean-->JSP。项目的目录结构:

一、实现DBHelper类:

该类的主要作用是取得数据库的连接并关闭相关资源。

1 packageutil;2

3 importjava.sql.Connection;4 importjava.sql.DriverManager;5 importjava.sql.PreparedStatement;6 importjava.sql.ResultSet;7 importjava.sql.SQLException;8

9 public classDBHelper {10 private static final String DRIVER = "com.mysql.jdbc.Driver";11 private static final String URL = "jdbc:mysql://localhost:3306/shopping?useUnicode=true&characterEncoding=UTF-8";12 private static final String USER = "root";13 private static final String PASSWORD = "mysqladmin";14

15 private static Connection coon = null;//DB连接对象

16

17 /**静态代码块加载DB驱动*/

18 static{19 try{20 Class.forName(DRIVER);21 } catch(ClassNotFoundException e) {22 e.printStackTrace();23 }24 }25

26 /**Singleton设计模式返回DB连接对象*/

27 public static Connection getConnection() throwsSQLException {28 if (coon == null) {29 coon =DriverManager.getConnection(URL, USER, PASSWORD);30 returncoon;31 }32 returncoon;33 }34

35 /**清理资源-关闭DB结果集、释放语句对象*/

36 public static voidrelsaseResource(ResultSet rs,PreparedStatement pstmt){37 //释放结果集

38 if (rs != null) {39 try{40 rs.close();41 rs = null;42 } catch(SQLException e) {43 e.printStackTrace();44 }45 }46 //释放语句对象

47 if (pstmt != null) {48 try{49 pstmt.close();50 pstmt = null;51 } catch(SQLException e) {52 e.printStackTrace();53 }54 }55 }56

57 /**测试DB连接*/

58 public static voidmain(String[] args) {59 try{60 Connection connection =DBHelper.getConnection();61 if(connection!=null){62 System.out.println("数据库连接成功!");63 }else{64 System.out.println("数据库连接异常!");65 }66 } catch(SQLException e) {67 e.printStackTrace();68 }69 }70 }

View Code

如果shopping数据库没有创建可能会抛出异常只需要执行:

create database shopping;

二、商品实体类的设计:

在创建实体类之前先建立好数据库表:

数据库脚本:items.sql

1 /*

2 Navicat MySQL Data Transfer3

4 Source Server : MySQL505 Source Server Version : 500676 Source Host : localhost:33067 Source Database : shopping8

9 Target Server Type : MYSQL10 Target Server Version : 5006711 File Encoding : 6500112

13 Date: 2014-08-27 12:12:3114 */

15

16 SET FOREIGN_KEY_CHECKS=0;17

18 ------------------------------

19 --Table structure for items

20 ------------------------------

21 DROP TABLE IF EXISTS`items`;22 CREATE TABLE`items` (23 `id` int(11) NOT NULLauto_increment,24 `name` varchar(50) default NULL,25 `city` varchar(50) default NULL,26 `price` int(11) default NULL,27 `number` int(11) default NULL,28 `picture` varchar(500) default NULL,29 PRIMARY KEY(`id`)30 ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;31

32 ------------------------------

33 --Records of items

34 ------------------------------

35 INSERT INTO `items` VALUES ('1', '沃特篮球鞋', '佛山', '180', '500', '001.jpg');36 INSERT INTO `items` VALUES ('2', '安踏运动鞋', '福州', '120', '800', '002.jpg');37 INSERT INTO `items` VALUES ('3', '耐克运动鞋', '广州', '500', '1000', '003.jpg');38 INSERT INTO `items` VALUES ('4', '阿迪达斯T血衫', '上海', '388', '600', '004.jpg');39 INSERT INTO `items` VALUES ('5', '李宁文化衫', '广州', '180', '900', '005.jpg');40 INSERT INTO `items` VALUES ('6', '小米3', '北京', '1999', '3000', '006.jpg');41 INSERT INTO `items` VALUES ('7', '小米2S', '北京', '1299', '1000', '007.jpg');42 INSERT INTO `items` VALUES ('8', 'thinkpad笔记本', '北京', '6999', '500', '008.jpg');43 INSERT INTO `items` VALUES ('9', 'dell笔记本', '北京', '3999', '500', '009.jpg');44 INSERT INTO `items` VALUES ('10', 'ipad5', '北京', '5999', '500', '010.jpg');

View Code

在MySQL中查询:

建立实体类(Items):也就是javabean其属性与DB中的各个字段一一对应。

1 packageentity;2

3 /**

4 * 商品类(与DB中的表名一致)-javabean 属性和DB中表的字段完全一致5 */

6 public classItems {7 private intid;8 privateString name;9 privateString city;10 private intprice;11 private intnumber;12 privateString picture;13

14 publicItems() {15 }16

17 public intgetId() {18 returnid;19 }20

21 public void setId(intid) {22 this.id =id;23 }24

25 publicString getName() {26 returnname;27 }28

29 public voidsetName(String name) {30 this.name =name;31 }32

33 publicString getCity() {34 returncity;35 }36

37 public voidsetCity(String city) {38 this.city =city;39 }40

41 public intgetPrice() {42 returnprice;43 }44

45 public void setPrice(intprice) {46 this.price =price;47 }48

49 public intgetNumber() {50 returnnumber;51 }52

53 public void setNumber(intnumber) {54 this.number =number;55 }56

57 publicString getPicture() {58 returnpicture;59 }60

61 public voidsetPicture(String picture) {62 this.picture =picture;63 }64

65 }

View Code

三、实现业务逻辑类(数据访问层DAO)

该类需要完成的功能:

分析:

1.在index.jsp中我们需要展示所有的商品信息。——获得所有商品

2.当用户点击任意一种商品后会将id通过URL传递给details.jsp,而在details.jsp中我们需要——根据id获得对应商品。

3.根据Cookie传入的字符串获得最近浏览的5条记录。

思考:如何将浏览记录保存在Cookie中?

回答:只需要保存商品的ID即可,因为每个商品的ID是唯一的。

实现:把每次浏览的商品ID保存一个字符串中,将这个字符串保存在Cookie中,ID和ID之间用分隔符分隔,每次取出前5条记录。

显示所有商品的主页index.jsp

1

2

3

4 contentType="text/html; charset=utf-8"%>

5

6

7

8

9

欢迎光临网上商城

10

11 div{

12 float:left;

13 margin:10px;

14 }

15

16 div dd{

17 margin:0px;

18 font-size:10pt;

19 }

20

21 div dd.dd_name{

22 color:blue;

23 }

24

25 div dd.dd_city{

26 color:#000;

27 }

28

29

30

31

32

商品展示

33


34

35

36 border="0">

37

38

39

40

41 ItemsDAO itemsDAO= newItemsDAO();42 ArrayListlist=itemsDAO.getAllItems();43 if(list!=null&&list.size()>0){44 //遍历所有的商品45 for(Items item:list){46 %>

47

48

49

50 ">

51 "width="120"height="90"border="1"/>

52

53

54

55 产地:  价格:¥

56

57

58

59 }60 }61 %>

62

63

64

65

66

67

68

View Code

显示商品详细信息的details.jsp

1

2

3

4

5

6

7

8

欢迎光临网上商城

9

10 div{

11 float:left;

12 margin-left:30px;

13 margin-right:30px;

14 margin-top:5px;

15 margin-bottom:5px;

16 }

17 div dd{

18 margin:0px;

19 font-size:10pt;

20 }

21 div dd.dd_name22 {

23 color:blue;

24 }

25 div dd.dd_city26 {

27 color:#000;

28 }

29

30

31

32

33

商品详情


34

35

36

37

38

39 Items item= newItemsDAO().getItemsById(Integer.parseInt(request.getParameter("id")));40 if(item!=null){41 %>

42

43

44

45 "width="200"height="160"/>

46

47

48

49

50

51

产地:

52

53

54

价格:¥

55

56

57

58

59 }60 %>

61

62

63 Stringlist= "";64 //从客户端获得Cookie集合65 Cookie[]cookies=request.getCookies();66 if(cookies!=null&&cookies.length>0){67 for(Cookie c:cookies){68 if(c.getName().equals("ListViewCookie")){69 list=c.getValue();70 }71

72 String[] arr=list.split(",");73 //相同商品只在浏览记录中存放一次74 if(Arrays.binarySearch(arr, request.getParameter("id"))<0){75 list+=request.getParameter("id")+ ",";76 }77 //如果浏览记录超过1000条,则清空Cookie78 if(arr!=null&&arr.length>1000){79 list= "";//清零-置空串80 }81 Cookie cookie= newCookie("ListViewCookie",list);82 response.addCookie(cookie);83 }84 }85 %>

86

87

88

89 您浏览过的商品

90

91

92 ArrayListitemsList= newItemsDAO().getViewList(list);93 if(itemsList!=null&&itemsList.size()>0){94 for(Items i:itemsList){95 %>

96

97

98

"width="120"height="90"border="1" />

99

100 产地:  价格:¥

101

102

103

104 }105 }106 %>

107

108

109

110

111

112

113

View Code

主业务逻辑类ItemsDAO

1 packagedao;2

3 importjava.sql.Connection;4 importjava.sql.PreparedStatement;5 importjava.sql.ResultSet;6 importjava.sql.SQLException;7 importjava.util.ArrayList;8 importjava.util.Arrays;9

10 importutil.DBHelper;11

12 importentity.Items;13

14 /**

15 * 商品的业务逻辑类16 */

17 public classItemsDAO {18 /**获得所有的商品信息*/

19 public ArrayListgetAllItems() {20 ArrayList itemsList = new ArrayList();//商品集合

21

22 Connection coon = null;23 PreparedStatement pstmt = null;24 ResultSet rs = null;25

26 try{27 coon =DBHelper.getConnection();28 String sql = "select * from items;";//sql语句

29 pstmt =coon.prepareStatement(sql);30 rs =pstmt.executeQuery();31

32 while(rs.next()) {33 Items items = newItems();34 setItemsAttributes(rs, items);//为实体类【商品】设置属性【根据DB中的相关字段】

35 itemsList.add(items);//把1个商品加入集合

36 }37 returnitemsList;38 } catch(Exception e) {39 e.printStackTrace();40 return null;41 } finally{42 DBHelper.relsaseResource(rs, pstmt);43 }44 }45

46 /**根据数据库的结果集设置实体类的属性*/

47 private voidsetItemsAttributes(ResultSet rs, Items items)48 throwsSQLException {49 items.setId(rs.getInt("id"));50 items.setName(rs.getString("name"));51 items.setCity(rs.getString("city"));52 items.setPrice(rs.getInt("price"));53 items.setNumber(rs.getInt("number"));54 items.setPicture(rs.getString("picture"));55 }56

57 /**根据商品的id获得商品资料*/

58 public Items getItemsById(intid) {59 Connection coon = null;60 PreparedStatement pstmt = null;61 ResultSet rs = null;62

63 try{64 coon =DBHelper.getConnection();65 String sql = "select * from items where id=?;";66 pstmt =coon.prepareStatement(sql);67 pstmt.setInt(1, id);68 rs =pstmt.executeQuery();69

70 if(rs.next()) {71 Items items = newItems();72 setItemsAttributes(rs, items);73 returnitems;74 } else{75 return null;76 }77 } catch(Exception e) {78 e.printStackTrace();79 return null;80 } finally{81 DBHelper.relsaseResource(rs, pstmt);82 }83 }84

85 /**获取最近浏览的前5条商品信息*/

86 public ArrayListgetViewList(String list){87 ArrayListitemsList = new ArrayList();88 int iCount = 5;//每次返回5条

89 if (list!=null&&list.length()>0) {90 String[]temp=list.split(",");91 //显示最近浏览过的商品——倒序得到Cookie中保存的ID

92 if (temp.length>=iCount) {93 System.out.println("浏览记录大于等于5条");94 System.out.println(Arrays.toString(temp));95 for(int i = temp.length-1;i>=temp.length-iCount;i--){96 itemsList.add(getItemsById(Integer.parseInt(temp[i])));97 }98 }else{99 System.out.println("浏览记录小于5条");100 System.out.println(Arrays.toString(temp));101 for(int i = temp.length-1;i>=0;i--){102 itemsList.add(getItemsById(Integer.parseInt(temp[i])));103 }104 }105 returnitemsList;106 }else{107 return null;108 }109 }110 }

View Code

Tips:

解决中文乱码:

1)在执行获取请求参数前设置编码:

request.setCharacterEncoding(“汉字编码”);

2)转换字符编码:

1   //获取原始的请求参数值

2 String rawName = request.getParameter("name");3 //将请求参数值使用ISO-8859-1字符串分解成字节数组

4 byte[] rawBytes = rawName.getBytes("ISO-8859-1");5 //将字节数组重新编码成字符串

6 String name = new String(rawBytes , "gb2312");

3)获取请求参数同时转换编码:

request.getParameter(“name”).getBytes ("ISO-8859-1");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值