第二部分遗留了一个问题,就是在server.xml中配置的reloadable="true"的含义?
在MyEclipse中对于一个类保存即编译,不用显示地编译,编译之后要求服务器重启,就是reloadable为true的含义。
使用Servlet生成静态页面的流程:
浏览器(客户端)发出请求,服务器(Tomcat)接收请求,调用生成好的class文件,并把执行结果以html代码的形式发送给浏览器(即客户端)。
使用JSP
在webRoot目录下新建一个JSP页面(New->JSP(Advanced Templates)):test.jsp,在该文件的body标签中添加如下代码:
<body> <h1>Hello World</h1> <%= new java.util.Date().toLocaleString() %> <%System.out.println(new java.util.Date().toLocaleString()); %> </body>
浏览器中访问http://localhost:8080/test/test.jsp,可以得到和第二部分中的Servlet一样的效果,总结一下就是:Servlet是嵌套了HTML代码的Java类,而JSP是嵌套了一些Java代码的HTML文件,但两者本质上是一样的,Servlet能完成的事情JSP都可以完成,反之亦然。不过是JSP省去了配置web.xml文件这个步骤。
1、表单的使用
为了支持中文,将jsp文件中的pageEncoding置为"UTF-8",即pageEncoding="UTF-8"。编写代码如下:
<body> <form action="/test/SecondServlet"> 用户:<input type = "text" name = "username" size = "20"><br> 密码:<input type = "password" name = "password" size = "20"><br> <input type = "submit" value = "提交"> <input type = "reset" value = "重置"> </form> </body>
下面主要对表单的action做下说明:它表示当点击鼠标提交按钮时提交到哪里。下面我们编写对于SecondServlet这个资源的处理。我们放弃之前纯手工的方式,采用MyEclipse给我们提供的自动化的功能:在com.test.servlet包下面new一个Servlet,命名为SecondServlet,继承方法只保留doGet()和doPost(),点击next,其默认的映射URL为/servlet/SecondServlet,为了方便我们将其更改为/SecondServlet,删掉Display Name和Description,点击finish,切换到web.xml视图,可以看到相应的信息已经如愿添加进来:
<servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.test.servlet.MyServlet</servlet-class> </servlet> <servlet> <servlet-name>SecondServlet</servlet-name> <servlet-class>com.test.servlet.SecondServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/MyServ</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>SecondServlet</servlet-name> <url-pattern>/SecondServlet</url-pattern> </servlet-mapping>
切换到SecondServlet.java文件,其中有很多额外的注释和基础代码,我们将其删掉,形成下面的样子:
package com.test.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SecondServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
下面我们编写代码,使得SecondServlet实现一个功能:将客户在test.jsp中填入的用户名和密码,SecondServlet获取它,并且在一个jsp页面显示出来。如此便完成了一个简单的客户端和服务器端的交互。代码编写如下:
package com.test.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class SecondServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<HTML><HEAD><TITLE>Result</TITLE></HEAD>"); out.println("<BODY>"); out.println(username + "<br>"); out.println(password); out.println("</BODY></HTML>"); } }
重启Tomcat服务器,浏览器中键入http://localhost:8080/test/test.jsp,输入用户名hello和密码world,页面自动跳转到http://localhost:8080/test/SecondServlet?username=hello&password=world。
此外,表单默认的提交方式是get,当然我们也可以采取post方式:
<form action="/test/SecondServlet" method="post">
这样页面跳转的时候地址栏为:http://localhost:8080/test/SecondServlet,这就是采用get/post提交的表象的区别。
Get与Post的区别
- 处理方式不一样(协议本身规定的)
- 处理的方法不一样
- 地址栏呈现的结果不一样
2、JSP与Servlet的生成方式:
Servlet首先被编译为class文件,然后由服务器调用。
JSP首先被转化为Servlet(Java文件),然后再被编译为class文件,最后由服务器调用处理。
如何验证这一点?进入Tomcat下面的目录:D:\Program Files\apache-tomcat-6.0.44\work\Catalina\localhost\test\org\apache\jsp,可以看到test_jsp.java。
那么既然有了Servlet,为什么需要JSP,这是因为用JSP写的很简单的代码,用Servlet写会变得很复杂,看看test_jsp.java可以很直观的理解这一点。
3、编写稍复杂的Servlet
在com.test.servlet下新建一个servlet,命名为ThirdServlet,建立过程与SecondServlet如出一辙。这时候web.xml中会自动增添相关的配置。ThirdServlet.java源码如下:
package com.test.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Random; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ThirdServlet extends HttpServlet { private static String[] responses = { "Yes", "No", "Maybe", "Later", "It is your call", "Not a chance"}; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String reply = generateReply(); response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<HTML><HEAD><TITLE>Decision Maker</TITLE></HEAD>"); out.println("<BODY>"); out.println("<H1>Your answer is: ‘" + reply + "‘<H1>"); out.println("</BODY></HTML>"); } private String generateReply() { // randomly pick a response int respIndex = new Random().nextInt(responses.length); // return the response back to the caller return responses[respIndex]; } }
重启Tomcat,在http://localhost:8080/test/ThirdServlet中不断刷新,会得到随机的显示。
4、用JSP代替SecondServlet
在WebRoot中new一个名为result的jsp,接着对test.jsp中的表单做出更改:
<form action="result.jsp" method="get">
在result.jsp的body中添加如下代码:
<body> <%String username = request.getParameter("username"); String password = request.getParameter("password"); %> username: <%= username %><br> password: <%= password %> </body>
进入http://localhost:8080/test/test.jsp,填入信息hello、world,自动跳转到http://localhost:8080/test/result.jsp?username=hello&password=world
几点说明:
- request和response是JSP中的九个默认对象中的两个,不需要声明,直接可以使用,类比Java中的lang包不需要导入一样,它们使用太频繁,导致这种局面。
- username: <%= username %>,其中<%= %>是JSP表达式,用脚本的方式也可以: username: <% out.print(username);
- JSP中倒包:<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>,多个包的话用逗号分隔。
5、巩固JSP表达式
建立third.jsp,<body>标签中的代码如下:
<body> <%Calendar calendar = Calendar.getInstance(); int currentHour = calendar.get(Calendar.HOUR_OF_DAY); %> <% if(currentHour < 12){%> Good Morning! <%}else if(currentHour > 12 && currentHour < 18){ %> Good Afternoon! <%}else{ %> Good Evening! <%} %> </body>
在浏览器中刷新http://localhost:8080/test/third.jsp,可以得到当前系统时间是早上/中午/晚上。
JavaServer Pages(JSP)语法及内置对象
- JSP简介
在传统的网页HTML文件(*.htm,*.html)中假如Java程序片段(Scriptlet)和JSP标签,就构成了JSP网页。
Java程序片段可以操作数据库、重定向网页以及发送E-mail等,实现建立动态网站所需要的功能。
所有程序操作都在服务器端执行,网络上传送给客户端的仅是得到的结果,这样大大降低了对客户浏览器的要求,即使客户浏览器不支持Java,也可以访问JSP网页。
JSP文件结构及主要标签
<%@ page contentType="text/html;charset=gb2312" %> <%@ page import="java.util.*" %> ... <HTML> <BODY> 其他HTML语言 <% 符合Java语法的Java语句 %> 其他HTML语言 </BODY> </HTML>
JSP示例
JSP执行过程
JSP示例
- JSP语法概述
JSP原始代码中包含了JSP元素和Template(模板)data两类
Template data指的是JSP引擎不处理的部分,即标记<%......%>以外的部分,例如代码中的HTML的内容等,这些数据会直接传送到客户端的浏览器
JSP元素则是指将由JSP引擎直接处理的部分,这一部分必须符合Java语法,否则会导致编译错误
JSP语法分为三种不同的类型:
编译器指令(DIRECTIVE)例如:<%@ page import="java.io.*"%>,编译器指令包括包含指令、页指令和taglib指令,它们包含在<%@ %>卷标里,两个主要的指令是page与include。
脚本语法(SCRIPTING):包括HTML注释(<!--comments-->,这种注释发送到客户端,但不直接显示,在源代码中可以看到)、隐藏注释(<%--comments--%>,不发生到客户端,供程序员查看使用的)、声明、表达式、脚本段
动作语法(ACTION)例如:<jsp:forward>,<jsp:getProperty>,<jsp:setProperty>,<jsp:include>和<jsp:useBean>
JSP语法格式:<%! declaration;[declaration;]... %>,看下面的实例:
<body> <center> <%! Data date = new Date(); %> <%! int a, b, c; %> <% a = 12; b = a; c = a + b; %> <font color="blue"> <%=date.toString()%> </font><br> <b>a=<%= a %></b><br> <b>b=<%= b %></b><br> <b>c=<%= c %></b><br> </center> </body>
当然,我们把上面的两个!去掉也不影响执行结果,那么两者的区别在哪里呢?可以通过查看它生成的servlet代码,可以得到结论:带!的变量生成变量的位置是成员变量,不加!就是局部变量
表达式:
用于在页面上输出信息,语法格式:<%= expression %>
脚本段:
JSP语法格式:<% code fragment %>,参见一个jsp实例:
<%@ page language="java" pageEncoding="gb2312"%> <%! int condition; %> <html> <head> <title> test </title> </head> <body> <% condition = 1; switch(condition) { case 0: out.println("You must select condition 0!"+"<br>"); break; case 1: out.println("You must select condition 1!"+"<br>"); break; case 2: out.println("You must select condition 2!"+"<br>"); break; default: out.println("You select not in \"0, 1, 2\", select again!"+"<br>"); break; } %> </body> </html>
包含指令:
include指令:向当前页中插入一个静态文件的内容。JSP语法格式:<%@ include file="realativeURL">,如:
<%--a.jsp包含b.jsp--> <%@ page language="java" pageEncoding="gb2312"%> <html> <head> <title> test </title> </head> <body bgcolor="white"> <font color="blue"> The current date and time are <%@ include file="a.jsp" %> </font> </body> </html> <%--b.jsp--> <%@ page import="java.util.*" %> <%=new java.util.Date().toLocaleString() %>
Page指令:
Page指令用于定义JSP文件中的全局属性,语法格式:<%@ page [language="java"] [extends="package.class"] [import="{package.class | package.*}, ..."] [session="true | false"] [isThreadSafe="true | false"] [errorPage = "relativeURL"] [contentType = "mimeType[;charset=characterSet]" | "text/html;charset=ISO-8859-1"] [isErrorPage="true | false"] %>,其中重要的属性有:
1.language="java"声明脚本语言的种类,目前只能使用"java"
2.import="{package.class | package.*},..."需要导入的Java包的列表,这些包作用于程序段,表达式,以及声明。下面的包在JSP编译时已经导入了,所以不需要再指明了:java.lang.* java.servlet.* javax.servlet.jsp.* javax.servlet.http.*
3.errorPage="realativeURL"设置处理异常事件的JSP文件
4.isErrorPage="true | false"设置此页是否为出错页,如果被设置为true,你就能使用exception对象
taglib指令:
JSP语法格式:<%@ taglib uri="URIToTagLibrary" prefix="tagPrefix" %>,用于引入定制标签库
jsp:forward
<%--a.jsp跳转到b.jsp--> <%@ page contentType="text/html";charset=gb2312 pageEncoding="gb2312"%> <html> <head> <title> test </title> </head> <body > <jsp:forward page="b.jsp"> <jsp:param name="userName" value="riso"/> </jsp:forward> <%System.out.println("此段代码不会被执行"); %> </body> </html> <%--b.jsp--> <%@ page contentType="text/html";charset=gb2312 pageEncoding="gb2312"%> <% String userName=request.getParameter("userName"); String outStr="谢谢光临!"; outStr += useName; out.println(outStr); %>
jsp:include
包含一个静态或动态文件
<%--a.jsp include b.jsp--> <%@ page contentType="text/html";charset=gb2312 pageEncoding="gb2312"%> <html> <head> <title> test </title> </head> <body > <jsp:include page="b.jsp"> <jsp:param name="User" value="hello"/> </jsp:include> </body> </html> <%--b.jsp--> <% String username; username=request.getParameter("User"); out.println("Username is"+username+"<br>"); %>