URL重写
URL重写
是一种会话跟踪技术,它将一个或多个键值对
添加到URL
的查询字符串中,每个键值对
通常为 key=value
形式,格式如下所示:1
url?key_1=value_1&key_2=value_2...&key_n=value_n
注意,URL
和键值对
之间用问号?
来分割,键值对
之间用单与符号&
分割。URL
重写适合于在少数URL
之间传递信息
的情况下,它有如下限制:
URL
在某些浏览器上最大长度为2000字符,所以URL
重写可能无法传递大量数据。- 如果要传递
信息
到下一个资源,需要将信息
插入到URL
的查询字符串中,这种情况适用于动态页面之间传值,而不适用于静态页面之间传值; URL
重写需要在服务端上完成,所有的链接都必须带值,因此当一个页面存在很多链接时,其处理过程会是一个不小的挑战;- 对应信息中的某些字符,例如
空格
、单与符号&
和问号?
等必须用base64
编码,而编码和解码会增加开销; URL
的内容会显示在浏览器的地址栏上,所以URL
重写不适合用来传递敏感信息。
所以,URL
重写仅适合于在少量页面间
传递不敏感信息
的情况。
下面来写个Demo,实用URL重写在同一个页面中传递信息。
Demo
项目目录
穿件一个名为SessionManagement
的动态Java Web项目,然后创建项目结果如下所示:
完整代码
1 | package session.management; |
代码详解
URL映射
Servlet中的URL映射的注解如下所示:1
2
3
4
5
6//配置Servlet映射到URL
(
name = "RewriteURL",
// 为一个servlet匹配多个URL
urlPatterns ={"/test"}
)name
表示当前session.management.RewriteURL
这个Servlet
的部署名。urlPatterns
表示该Servlet
的URL
地址,这个是个数字形式,同一个Servlet
可以设置不同的URL
地址.
映射好URL后,后面就可以通过http://localhost:8080/项目名称/test
这样的格式来访问这个Servlet,这里是:
http://localhost:8080/SessionManagement/test
初始化数据
1 | private ArrayList<String> fruits = null; |
在这个Servlet中有两个成员变量fruits
和vegetables
用于存放要展示的数据。
当用户第一次通过URL
访问到该Servelet
时,Web
容器(Tomcat)会调用init()
方法来初始化数据。在这里,init()方法用来初始化成员变量的数据。
响应get请求 覆盖doGet方法
当直接通过http://localhost:8080/SessionManagement/test这个URL访问的时候,Tomcat会调用init()方法来初始化,初始化只进行一次.后面不再调用init()方法.然后调用doGet()方法来响应请求。doGet方法如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
// 获取查询字符串
String choice = request.getParameter("choice");
//
if (choice == null) {
showIndex(response);
} else if ("fruits".equals(choice)) {
//如果用户选择了水果的显示水果
showFruits(response);
} else if ("vegetables".equals(choice)) {
//如果用户选择了蔬菜的显示蔬菜
showVegetables(response);
}
}
doGet方法会获取请求中名称为choice
的参数值。然后根据参数值的不同来调用不同的方法进行响应。
当我们请求http://localhost:8080/SessionManagement/test对应的Servlet时,URL中没有带查询字符串,所以不存在choice这个参数。request.getParameter("choice");
返回null.这样就会调用showIndex(response);
这个方法来响应。
返回初始界面
showIndex()方法如下,所谓的响应,就是往响应对象里写一些字符串。Web容器会把响应对象中的这些字符串处理一下然后发送给浏览器。
1 | private void showIndex(HttpServletResponse response) |
此时浏览器显示如下:
这个页面有两个超链接,如下所示:1
2<a href="?choice=fruits">显示水果</a>
<a href="?choice=vegetables">显示蔬菜</a>
响应重写的URL
在刚才的页面中,显示水果
的URL为?choice=fruits
这是个查询字符串,查询字符串中有一个名为choice
的参数,参数值为fruits
。
如果点击这超链接,浏览器会再次发送一个HTTP请求给服务器。
这里URL中地址缺省,浏览器会默认发给当前的地址。也就是在http://localhost:8080/SessionManagement/test
这个地址后面加上查询字符串,得到的URL为:http://localhost:8080/SessionManagement/test?choice=fruits
,这相当于重写了URL
.
虽然,这个时候请求的Servlet还是http://localhost:8080/SessionManagement/test
这个URL对应的Servlet.但是这回跟第一次请求时的情况是不一样的,第一次没有带请求参数,这次带了请求参数。Tomcat还是会调用doGet来生成响应。
不过这次因为带了参数choice=fruits
,doGet方法会调用showFruits
方法来生成响应。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36private void showFruits(HttpServletResponse response)
{
// 设置响应的格式为HTML
response.setContentType("text/html");
//因为响应带有中文,设置编码格式为中文,不然会出现中文乱码??????这种情况。
response.setCharacterEncoding("UTF-8");
PrintWriter writer;
try {
// 获取响应输出
writer = response.getWriter();
// 生成水果列表
String ul = "";
for (String string : fruits) {
ul += "<li>" + string + "</li>";
}
//拼接成完整的HTML内容
String responseHTML =
"<html>\r\n" +
" <head>\r\n"+
" <meta charset=\"utf-8\">\r\n"+
" <title>测试URL重写</title>\r\n" +
" </head>\r\n"+
" <body>\r\n" +
" <hr>\r\n" + ul +
" <hr>\r\n"+
" <a href=\"?choice=fruits\">显示水果</a> \r\n"+
" <a href=\"?choice=vegetables\">显示蔬菜</a>\r\n"+
" </body>\r\n" +
"</html>";
// 输出响应对象中
writer.write(responseHTML);
//Servlet容器被把响应对象中的响应发给浏览器,我们不用管
} catch (IOException e) {
e.printStackTrace();
}
}
这个方法会把水果列表中的数据输出。如下所示:
同理如果此时点击显示蔬菜
链接我们就可以显示蔬菜。