JavaWeb-会话技术之session&JSP
会话管理之Session技术
一、Session
在WEB开发中,server能够为每一个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此。在须要保存用户数据时。server程序能够把用户数据写到用户浏览器独占的session中,当用户使用浏览器訪问其他程序时,其他程序能够从用户的session中取出该用户的数据,为用户服务。
1、Session和Cookie的主要差别在于:
a. Cookie是把用户的数据写给用户的浏览器。
b. Session技术把用户的数据写到用户独占的session中。
c. Session对象由server创建。开发者能够调用request对象的getSession方法得到session对象。
2、怎样创建session:
1) request.getSession() ;
此方法做了2件事:
1. 先看浏览器是否携带了一个名字叫JSESSIONiD的Cookie,假设没有,则直接创建一个新的session
2. 假设有,则依据Cookie的值去服务端的内存中寻找id的值是此值的session.而且返回,找不到。创建新的返回
2) request.getSession(boolean flag) ;
假设flag为true,则相当于情况1)
假设flag为false,则仅仅查不创建。
3、服务端发送的JSESSIONID默认情况下存储在client的缓存中,所以关闭浏览器,session的生命就结束了,要想多个关闭后还能用,那么必须创建一个新的Cookie,名字也是JSESSIONID,设置存活时间,此时cookie存储在client的硬盘上,下次打开新的浏览器訪问,浏览器会携带此Cookie,也就达到了关闭浏览器还能使用此Session的效果了。
二、session案例
session实现原理+样例实验演示session原理(session1与session2之间的通话)。演示效果,在凝视掉把session存储到硬盘上的代码后。给session设置属性。然后用sessin2来訪问属性,假设在本地cookie没有文件的情况下,在訪问了一次session1然后关掉浏览器。浏览器是不存储cookie,这么样session2是获取不了session产生的信息属性的。
1、使用Session完毕用户登陆;
利用Session实现一次性验证码:不足:但用户单击”刷新”,或单击”后退”再次提交表单,将导致表单反复提交
a. 一次性验证码的主要目的就是为了限制人们利用工具软件来暴力推測password。
b. server程序接收到表单数据后。首先推断用户是否填写了正确的验证码,仅仅有该验证码与server端保存的验证码匹配时。server程序才開始正常的表单处理流程。
c.password推測工具要逐一尝试每一个password的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了password推測工具的自己主动地处理过程。
项目架构:
配置文件web.xml内容例如以下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>ServletResponse3</servlet-name>
<servlet-class>com.heima.session.ServletResponse3</servlet-class>
</servlet>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.heima.session.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletResponse3</servlet-name>
<url-pattern>/servlet/ServletResponse3</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/servlet/LoginServlet</url-pattern>
</servlet-mapping>
<display-name></display-name>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
</web-app>
login.html
<!DOCTYPE html>
<html>
<head>
<title>MyHtml.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/./styles.css">-->
</head>
<script type="text/javascript">
function changeImage(){
//拿到图片对象
var image = document.getElementById("img") ;
//设置src属性
image.src = "/day10_01_login/servlet/ServletResponse3?t=" +new Date() ;
}
</script>
<body>
<form action="/day10_01_login/servlet/LoginServlet" method="post">
<table border =1 >
<tr>
<td><br><br> 姓名:</td>
<td><input type = "text" name = "username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type = "password" name = "pass"></td>
</tr>
<tr>
<td>请输入验证码:</td>
<td><input type = "text" name = "code"> <img src = "/day10_01_login/servlet/ServletResponse3" id = "img"> <a href = "javascript:changeImage()">看不清楚,换一张</a></td>
</tr>
<tr>
<td colspan = "2"><input type="submit" value = "登录"> </td>
</tr>
</table>
</form>
</body>
</html>
main.html
<!DOCTYPE html>
<html>
<head>
<title>main.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="http://blog.163.com/faith_yee/blog/./styles.css">-->
</head>
<body>
欢迎进入主页面
</body>
</html>
LoginServlet.java
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;
import javax.servlet.http.HttpSession;
//演示用户通过验证码登陆
public class LoginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter() ;
//先拿到页面的传递的数据
String username = request.getParameter("username") ;
String pass = request.getParameter("pass") ;
String code = request.getParameter("code") ;
//先推断code
//从session中拿取验证码
HttpSession session = request.getSession() ;
String scode = (String) session.getAttribute("code") ;
if(!scode.equals(code)){
request.setAttribute("error", "验证码不对,请又一次输入") ;
request.getRequestDispatcher("/login.html").forward(request, response) ;
return ;
}
if("张三".equals(username) && "111".equals(pass)){
session.setAttribute("loginuser", "张三") ;
out.write("欢迎你," +username + "进入主页" ) ;
request.getRequestDispatcher("/main.html").forward(request, response) ;
}else{
//非法用户
// request.setAttribute("error", "用户名或者password错误") ;
out.write("用户名或者password错误,2秒后转向登陆页面") ;
response.setHeader("Refresh", "2;url='" + request.getContextPath() +"/login.html'") ;
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ServletResponse3.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//演示验证码的生成
public class ServletResponse3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置图片的宽度。高度
int width = 120 ;
int height = 30 ;
//创建图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) ;
//拿到图片的画笔
Graphics g = image.getGraphics() ;
//设置边框的颜色
g.setColor(Color.RED) ;
//将图片画出来
g.drawRect(0, 0, width, height) ;
//填充一下背景
g.setColor(Color.yellow) ;
//填充背景
g.fillRect(1, 1, width-2, height-2) ;
//画4个数字
Random r = new Random() ;
g.setColor(Color.red) ;
g.setFont(new Font("幼圆", Font.BOLD + Font.ITALIC, 18)) ;
// for (int i = 0; i < 4; i++) {
// g.drawString(r.nextInt(10) + "", 20 + i*20, 20) ;
// }
//随机画30条干扰线
g.setColor(Color.gray) ;
for (int i = 0; i < 30; i++) {
g.drawLine(r.nextInt(width), r.nextInt(height),r.nextInt(width), r.nextInt(height)) ;
}
//画中文
g.setColor(Color.red) ;
String s = "中国好声音深圳黑马训练营Ilovemoney" ;
s = "u4E2Du56FDu597Du58F0u97F3u6DF1u5733u9ED1u9A6Cu8BADu7EC3u8425Ilovemoney" ;
StringBuffer sb = new StringBuffer() ;
for (int i = 0; i < 4; i++) {
char c = s.charAt(r.nextInt(s.length())) ;
sb.append(c) ;
g.drawString(c + "", 20 + i*20 + r.nextInt(5), 18 + r.nextInt(5)) ;
}
//将验证码放入session中
request.getSession().setAttribute("code", sb.toString()) ;
response.setHeader("Expires", "-1") ;
response.setHeader("Cache-Control", "no-cache") ; //使用1.1协议
response.setHeader("Pragma", "no-cache") ; //使用1.0协议
//创建imageIO对象
ImageIO.write(image, "jpg", response.getOutputStream()) ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在浏览器中输入:http://localhost:8080/day1001login/login.html,进入例如以下界面:
在输入错误的账号password或验证码,则进入下面页面并在2秒后返回:
在输入正确的信息之后:
得到下面结果:
2、利用Session防止表单反复提交
1、表单页面由servlet程序生成,servlet为每次产生的表单页面分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同一时候在当前用户的Session域中保存这个标识号。
2、当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比較,假设同样则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
3、在下列情况下,server程序将拒绝用户提交的表单请求:
a. 存储Session域中的表单标识号与表单提交的标识号不同
b. 当前用户的Session中不存在表单标识号
c. 用户提交的表单数据中没有标识号字段
项目架构:
配置文件web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<servlet>
<servlet-name>RegisterUIServlet</servlet-name>
<servlet-class>com.heima.servlet.RegisterUIServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.heima.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterUIServlet</servlet-name>
<url-pattern>/servlet/RegisterUIServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/servlet/RegisterServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
RegisterUIServlet.java
import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sun.misc.BASE64Encoder;
//作用是生成注冊页面
public class RegisterUIServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter() ;
//code是唯一生成的值
String code = "";
//第一种方式
//code = System.nanoTime() + "" ; //理论上有反复的可能,实际上不可能
code = System.nanoTime() + "" + new Random().nextLong() ;
//另外一种方式
code = UUID.randomUUID().toString() ; //理论和实际都是唯一
//第三种:数据指纹
code = System.nanoTime() + "" + new Random().nextLong() ;
byte[] bs = code.getBytes() ;
MessageDigest md = null;
try {
md = MessageDigest.getInstance("md5");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bs = md.digest(bs) ;
BASE64Encoder base = new BASE64Encoder() ;
code = base.encode(bs) ; //数据指纹
//将指纹应当在session中存储一份
request.getSession().setAttribute("code", code) ;
//生成页面
out.write("<form action = '" + request.getContextPath()+"/servlet/RegisterServlet' method = 'post'>") ;
out.write("姓名:<input type = 'text' name = 'username'><br>") ;
out.write("<input type = 'hidden' name = 'code' value = '" + code +"'><br>") ;
out.write("<input type = 'submit' value = '注冊'><br>") ;
out.write("</form><br>") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
- 注意。在使用数据指纹时project须要进行手动设置一下。过程例如以下:
对项目project点击右键选择Build Path-->Configure Build Path
在Java Build Path对话框中点击Libraries栏目:在EAR Libraries包下的Access rules,点击右下的Editbutton
进入该对话框。点击Edit对Accessible属性进行设置
下拉框选择Accessible
在Rule Pattern输入**点击OK设置完成。
RegisterServlet.java
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 RegisterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out =response.getWriter() ;
//从session中拿取口令和client传递过来的口令进行比較
String fcode = request.getParameter("code") ;
String username = request.getParameter("username") ;
//从session中拿到令牌
String scode = (String) request.getSession().getAttribute("code") ;
if(!fcode.equals(scode)){
//说明反复提交了
out.write("不要反复提交,2秒后转向注冊页面") ;
response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/servlet/RegisterUIServlet") ;
}else{
//正常提交
out.write(username + "已经放入了数据库") ;
//将口令废除
request.getSession().removeAttribute("code") ;
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在浏览器输入:http://localhost:8080/day1002token/servlet/RegisterUIServlet,进入例如以下界面:
输入yw进入例如以下界面:
当在该界面点击刷新button时出现例如以下对话框阻止数据再次提交
观察httpwatch插件中的浏览器接收到的信息,第一次输入yw是server返回给浏览器的头信息
第二次点击刷新button时server返回给浏览器的头信息,发现server没有返回给浏览器所提交的信息。
3、IE禁用Cookie后的session处理
实验演示禁用Cookie后servlet共享数据导致的问题。
解决方式:URL重写
response. encodeRedirectURL(java.lang.String?url)
用于对sendRedirect方法后的url地址进行重写。
response. encodeURL(java.lang.String?url)
用于对表单action和超链接的url地址进行重写
附加:
Session的失效 invalidate()立马实效
Web.xml文件配置session失效时间
总结:cookie私隐安全性最高时。计算机不接受cookie文件。
那么server怎么办?项目encodeURL。
演示URL重写:session本质上也是浏览器发送了一个cookie。但在隐私那里设置了最高隐私。那么浏览器不会接受不论什么cookie和发送cookie。正常情况下这样server都会在浏览器每次訪问server的时候都新建一个session。但一般站点是觉得假设浏览器若禁止了cookie,那么server会禁止浏览器的訪问。
第二种情况:叫URL重写。就是在server提供的超链上同一时候写上cookie的代码,一并提交到server上。
(禁止cookie里的两个项目,第一个项目为了演示url重写的效果,第二个项目配合第一个项目为了演示在一个已经设置了最高权限不带接收和携带不论什么cookie的浏览器訪问server中的项目1时,当不关闭浏览器那么浏览器再输入第二个项目的地址后是否能拿得到项目1里的数据?答案是拿不到,由于没有通过项目1给的超链去訪问项目2,浏览器是不带有不论什么cookie在身上的。所以在项目2中没法知道项目1的不论什么信息。)
项目架构:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<servlet>
<servlet-name>ServletEncodeURL</servlet-name>
<servlet-class>com.heima.servlet.ServletEncodeURL</servlet-class>
</servlet>
<servlet>
<servlet-name>ServletEncodURL</servlet-name>
<servlet-class>com.heima.servlet.ServletURL</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletEncodeURL</servlet-name>
<url-pattern>/servlet/ServletEncodeURL</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletEncodURL</servlet-name>
<url-pattern>/servlet/ServletURL</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
ServletEncodeURL.java
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;
import javax.servlet.http.HttpSession;
//演示URL重写
public class ServletEncodeURL extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter() ;
String url = request.getContextPath() + "/servlet/ServletURL" ;
System.out.println("重写前:" + url);
HttpSession session = request.getSession() ;
session.setAttribute("name", "张三风") ;
System.out.println(session.getId()) ;
//对url进行重写,(目的就是将session的唯一的id附加在网址后面)
url = response.encodeURL(url) ;
System.out.println("重写后:" + url);
out.write("<a href='http://blog.163.com/faith_yee/blog/" + url +"'>a.html</a>") ;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
ServletURL.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class ServletURL extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//从session中拿取数据
HttpSession session = request.getSession() ;
String name = (String) session.getAttribute("name") ;
System.out.println(name);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
在浏览器中输入:http://localhost:8080/day1003encodeURL/servlet/ServletEncodeURL,进入下面页面:
4、固化状态:
项目:
当server停止的时候,内存中的session将会固化到硬盘上,路径在workCatalinalocalhostday1104sessionseria下,文件后缀名是ser.当又一次启动的时候,此文件对象会自己主动又被读入内存继续服务。
总结:又一次启动了电脑(server),如何防止session丢失?就使用到了固化机制存储session到硬盘上,session.ser在server目录里寻找。这文件叫固化或搁置。当server又一次启动之后。目录里的session.ser就没了。用户继续在当前IE中浏览还能够导出session的内容
session的状态:
JSP技术基础
一、什么是JSP?
JSP全称是Java Server Pages。它和servle技术一样。都是SUN公司定义的一种用于开发动态web资源的技术。JSP/Servlet规范。
JSP实际上就是Servlet。
JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html仅仅能为用户提供静态数据,而Jsp技术同意在页面中嵌套java代码,为用户提供动态数据。
提问:为什么JSP技术也是一种动态web资源的开发技术?
答:由于JSP技术同意在页面中嵌套java代码,以产生动态数据,而且webserver在运行jsp时。webserver会传递web开发相关的对象给jsp,jsp通过这些对象,能够与浏览器进行交互,所以jsp当然也是一种动态web资源开发技术。
强调一个概念:对如今的用户而言,觉得通过浏览器看到的东西都是网页。但我们程序猿心里要清楚。开一个浏览器訪问网页,这些网页有可能是一个html页面(即静态web资源),也有可能是一个动态web资源(即servlet或jsp程序输出的)。
JSP技术概述:
实例 jsp里能够有4种代码:html+css+js+java。在jsp里的java代码用<% %>标签来包含。
在project里生成的xx.jsp文件首先会在server的work文档里生成_xx.java文件,里面的java类继承了org.apache.jasper.runtime.HttpJspBase ,并重写了该类里面的内容,server会把java文件编译之后运行java里面的代码。该java类事实上就是一个servlet程序。由于org.apache.jasper.runtime.HttpJspBase里面继承了httpservlet类
在创建jsp文件时怎么提前设置server让其新建的jsp文件都是pageEncoding="UTF-8" ?在project名点击右键进入Properties选项里的MyEclipse的JSP Fragments里选择语言。或者改jsp的模板来改变
二、JSP原理
1、IE浏览器訪问JSP页面时。Webserver是怎样调用并运行一个jsp页面的?(Servlet)
答:当IE浏览器訪问server中的jsp文件时,server会把jsp文件编译成_xx.java这样一个servlet类
2、Webserver在运行jsp页面时,是怎样把Jsp页面中的html排版标签发送到client的?
Out.write();
3、Jsp页面中的java代码server是怎样运行的?
运行并发送
4、Webserver在调用jsp时,会给jsp提供一些什么java对象?
九大对象:
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
因为这九大对象已经在server实例化了。在jsp中不须要编译就能够直接使用,所以在编写jsp代码的时候不须要又一次启动server就能够直接在浏览器上刷新測试。
三、JSP最佳实践
1、无论是JSP还是Servlet,尽管都能够用于开发动态web资源。但因为这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。
2、其原由于。程序的数据通常要美化后再输出:
3、让JSP既用java代码产生动态数据,又做美化会导致页面难以维护。
4、让servlet既产生数据,又在里面嵌套html代码美化数据,相同也会导致程序可读性差,难以维护。
5、因此最好的办法就是依据这两门技术的特点,让它们各自负责各得,servlet仅仅负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。
实验一:了解JSP
项目结构:
1.jsp
<%@ page language="java" import="java.util.*" pageEncoding="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="http://blog.163.com/faith_yee/blog/<%=basePath%>">
<title>My JSP '1.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="http://blog.163.com/faith_yee/blog/styles.css">
-->
</head>
<body>
<%
out.write(new Date().toLocaleString()) ;
request.setAttribute("name", "东方不败") ;
String name = (String) request.getAttribute("name") ;
out.write(name) ;
%>
</body>
</html>
2.jsp
<%@ page language="java" import="java.util.*" pageEncoding="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="http://blog.163.com/faith_yee/blog/<%=basePath%>">
<title>My JSP '2.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="http://blog.163.com/faith_yee/blog/styles.css">
-->
</head>
<body>
This is my JSP page.<br>
</body>
</html>
在浏览器输入:http://localhost:8080/day1004jsp/1.jsp
在浏览器输入:http://localhost:8080/day1004jsp/2.jsp