Servlet进阶(链接传值、XML配置、转发与重定向)
引言:
本文主要分享了Servlet中的GET提交和POST提交的区别、解释了Servlet基础一文中的连接传值、Servlet的声明周期、中文乱码问题的解决、XML文件的若干配置以及转发与重定向的应用;
@[toc]
1. 链接传值
相当于GET提交,短的字符串或者数字可以使用连接传值来代替表单传值
1.1 配置web.xml
<!--声明Servlet-->
<servlet>
<!--servlet的名称-->
<servlet-name>myServlet</servlet-name>
<!--servlet的全类名-->
<servlet-class>com.kaka.controller.ServletDemo</servlet-class>
</servlet>
<!--给Servlet设置访问名称-->
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<!--servlet的访问名称-->
<url-pattern>/demo</url-pattern>
</servlet-mapping>
1.2 编写index.html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="demo">
ID:<input type = "text" name = "id"/><br/>
NAME:<input type = "text" name = "name"/><br/>
<input type = "submit" name = "submit"/>
</form>
</body>
</html>
1.3 编写success.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
NAME:<%=request.getParameter("name") %><br/>
SCORE:<%=request.getParameter("score") %><br/>
</body>
</html>
1.4 编写ServletDemo.java
package com.kaka.controller;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo extends HttpServlet{
protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
//获取参数的方法
String id = arg0.getParameter("id");
String name = arg0.getParameter("name");
System.out.println(id + "\t" + name);
//获取URL
StringBuffer url = arg0.getRequestURL();
System.out.println(url);
//获取方法
String method = arg0.getMethod();
System.out.println(method);
//获取键值对
Map<String, String[]> parameterMap = arg0.getParameterMap();
//获取键
Set<String> keySet = parameterMap.keySet();
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
String[] value = (String[])parameterMap.get(key);
System.out.println("key:"+key+"value:"+Arrays.toString(value));
}
arg0.getRequestDispatcher("success.jsp?name=admin&score=90").forward(arg0, arg1);
}
}
1.5 运行结果
点击form表单结果
点击连接传值结果
1.6 小结
通过上述代码运行可以得出:
点击提交后生成
http://localhost:8080/JavaWeb_2020_07_16/demo?id=1&name=kaka链接;
符合URL的格式:
协议+ ://+ip+:+端口+/资源地址?key1=value1&key2=value2
连接传值为GET提交的方式;
两种方式都可以传值成功区别是利用表单后台id、name有值,利用连接传没有值;
使用链接传值时一定要保证KEY值与被传页面保持一致;
2. Get提交与Post提交的区别
2.1 配置web.xml
<servlet>
<servlet-name>Servlets</servlet-name>
<servlet-class>com.kaka.controller.StuServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Servlets</servlet-name>
<url-pattern>/stu</url-pattern>
</servlet-mapping>
2.2 编写addStudent.html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="stu" medthod="GET">
ID:<input type="text" name="id" value=""/><br/>
NAME:<input type="text" name="name" value="" /><br/>
<input type="submit" value="GETsubmit"/>
</form>
<p/>
<form action="stu" method="POST" >
ID:<input type="text" name="id" value=""/><br/>
NAME:<input type="text" name="name" value="" /><br/>
<input type="submit" value="POSTsubmit"/>
</form>
</body>
</html>
2.3 编写StuServlet.java代码
2.3.1 doGet和doPost
package com.kaka.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class StuServlet extends HttpServlet {
public StuServlet() {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String name = request.getParameter("name");
System.out.println(id+"\t"+name+"\t"+"method:GET");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String name = request.getParameter("name");
System.out.println(id+"\t"+name+"\t"+"method:POST");
}
}
运行结果:
2.3.2 service、doGet和doPost的优先级
package com.kaka.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class StuServlet extends HttpServlet {
public StuServlet() {
}
protected void service(HttpServletRequest request, HttpServletResponse respone) throws ServletException, IOException {
String id = request.getParameter("id");
String name = request.getParameter("name");
System.out.println(id+"\t"+name+"\t"+"method:Service");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String name = request.getParameter("name");
System.out.println(id+"\t"+name+"\t"+"method:GET");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String name = request.getParameter("name");
System.out.println(id+"\t"+name+"\t"+"method:POST");
}
}
运行结果:
2.3.3 常用版Servlet代码
package com.kaka.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class StuServlet extends HttpServlet {
public StuServlet() {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String name = request.getParameter("name");
System.out.println(id+"\t"+name);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
运行结果:
2.4 小结
通过上述代码运行可以得出:
- 当form表单method=get时 ,默认提交后执行servlet的doGet方法;
- 当form表单method=post时 ,默认提交后执行servlet的doPOST方法;
- servlet在创建时会创建父类的对象,先执行父类HttpServlet的service方法,根据请求的method取值调用不同的处理方法模型为 :doGet、doPost、doDelete、doPut;
- 在自定义的servlet中重写这些方法对应做不同的请求处理;
- 当servlet重写service方法时,do*系列方法将不再执行;
- 最终版本的当执行了Post时执行doPost请求又转向doGet;
3. Servlet的生命周期
3.1 生命周期
一个事物从开始到存活再到结束也就是需要看Servlet的初始化、存活以及销毁;
3.2 Servlet的生命周期特点
- servlet初始化:Servlet默认不是随着服务器的启动而初始化,当第一次访问Servlet时才初始化,后面访问就执行处理请求,不会初始化了;
- servlet销毁:服务器关闭的时候会销毁Servlet;
- Servlet在服务器中是一个单例(不会占用过多的内存);
package com.kaka.controller;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class StuServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
//只启动一次
public StuServlet() {
System.out.println("constructor....构造函数");
}
//可执行多次
protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
String id = arg0.getParameter("id");
String name = arg0.getParameter("name");
System.out.println("service...服务"+id+"\t"+name);
}
//执行一次
public void destroy() {
System.out.println("destroy...销毁");
super.destroy();
}
//执行一次
public void init(ServletConfig config) throws ServletException {
System.out.println("init...初始化");
}
}
运行结果:
注意:
- 当servlet含有load-on-startup配置时,该servlet会在容器(servlet引擎)启动自动创建对象,并初始化,等待请求到来;
- 当没有load-on-startup时,容器启动时,不创建servlet对象,当第一个请求到来时根据反射创建该servlet对象,并初始化,再执行服务;当下一次请求到来时,直接执行service方法提供服务
- 当服务器正常关闭时,容器会调用destroy方法回收servlet占用的资源;
4. 解决中文乱码问题
4.1 配置xml文件
<servlet>
<servlet-name>stuServlet</servlet-name>
<servlet-class>com.kaka.controller.StuServlet</servlet-class>
<!-- 设置servlet的初始化参数 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>stuServlet</servlet-name>
<url-pattern>/stu</url-pattern>
</servlet-mapping>
4.2 编写index.html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="stu" medthod="GET">
ID:<input type="text" name="id" value=""/><br/>
NAME:<input type="text" name="name" value="" /><br/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
4.3 编写stuServlet.java文件
package com.kaka.controller;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class StuServlet extends HttpServlet {
private final static String oldEncoding = "ISO-8859-1";
private static String newEncoding = null;
//只启动一次
public StuServlet() {
System.out.println("constructor....构造函数");
}
//执行一次
public void init(ServletConfig config) throws ServletException {
newEncoding = config.getInitParameter("encoding");
System.out.println("init...初始化");
}
//可执行多次
protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
String id = arg0.getParameter("id");
String name = arg0.getParameter("name");
//转码
String newName = new String(name.getBytes(oldEncoding),newEncoding);
System.out.println("service...服务"+id+"\t"+newName);
}
//执行一次
public void destroy() {
System.out.println("destroy...销毁");
super.destroy();
}
}
运行结果:
5. load on startup配置
根据Servlet生命周期可知Servlet默认不会随着服务器的启动而初始化,进行load on startup配置可以让servlet随着服务器的启动而初始化;
有10个优先级:1~10;数字越小,优先级越高;
当服务器启动时,load on startup值为1的先初始化,然后再初始化值为2的,以此类推;
<servlet>
<servlet-name>TestServlet05</servlet-name>
<servlet-class>com.kaka.test_01.servlet.TestServlet05</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet05</servlet-name>
<url-pattern>/Demo05</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>TestServlet06</servlet-name>
<servlet-class>com.kaka.test_01.servlet.TestServlet06</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet06</servlet-name>
<url-pattern>/Demo06</url-pattern>
</servlet-mapping>
</web-app>
- 以上代码首先初始化TestServlet06在初始化TestServlet05;
6. Servlet中的xml的配置
自定义Servlet:
- 声明该Servlet;
- 给该Servlet配置访问路径;
6.1 Servlet可以有多个访问名称
给对应的Servlet多个servlet-mapping标签
<servlet>
<servlet-name>TestServlet07</servlet-name>
<servlet-class>com.kaka.test_01.servlet.TestServlet07</servlet-class>
</servlet>
<!--第一个访问名称-->
<servlet-mapping>
<servlet-name>TestServlet07</servlet-name>
<url-pattern>/Demo07_01</url-pattern>
</servlet-mapping>
<!--第二个访问名称-->
<servlet-mapping>
<servlet-name>TestServlet07</servlet-name>
<url-pattern>/Demo07_02</url-pattern>
</servlet-mapping>
6.2 url-parttern的书写规则
6.2.1 完全匹配
要求网址上的访问名称完全和url-parttern一致
必须以"/"开头,否则会报错:IllegalArgumentException : Invalid url-pattern;
<!--使用完全匹配-->
<servlet>
<servlet-name>TestServlet07</servlet-name>
<servlet-class>com.kaka.test_01.servlet.TestServlet07</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet07</servlet-name>
<url-pattern>/Demo07</url-pattern>
</servlet-mapping>
6.2.2 目录匹配
要求网址上的访问名称中的目录和url-parttern一致
必须以"/"开头,以"*"结尾
如:/a/b/* , 目录必须是/a/b,后面随便写
<!--使用目录匹配-->
<servlet>
<servlet-name>TestServlet08</servlet-name>
<servlet-class>com.kaka.test_01.servlet.TestServlet8</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet08</servlet-name>
<url-pattern>/a/b/*</url-pattern>
</servlet-mapping>
6.2.3 后缀名匹配
要求网址上的访问名称中的后缀和url-parttern一致
不能以"/"开头,以"*"开头,后缀名根据业务写
如:*.xyz。后缀名必须是xyz,其他随意写
<!--使用后缀名匹配-->
<servlet>
<servlet-name>TestServlet09</servlet-name>
<servlet-class>com.kaka.test_01.servlet.TestServlet09</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet09</servlet-name>
<url-pattern>*.xyz</url-pattern>
</servlet-mapping>
7. 转发与重定向
7.1 概述
转发的作用在服务器端,将请求发送给服务器上的其他资源,共同完成一次处理;
重定向作用在客户端,客户端将请求发送给服务器后,服务端响应一个新的请求地址,客户端重新发送新请求;
页面跳转:
- 转发:request.getRequestDispatcher("/目标URL-patten").forward(request,response);
- 重定向:response.sendRedirect("目标URL");
7.1 编写xml文件
<servlet>
<servlet-name>stuServlet</servlet-name>
<servlet-class>com.kaka.controller.RedirectServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>stuServlet</servlet-name>
<url-pattern>/stu</url-pattern>
</servlet-mapping>
7.2 编写home.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>home view.....</h2>
id:<%=request.getAttribute("id") %><br/>
name:<%=request.getParameter("name") %>
</body>
</html>
7.3 编写RedirectServlet.java代码
package com.kaka.controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RedirectServlet extends HttpServlet{
protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
System.out.println("提供服务......");
String id = arg0.getParameter("id");
if("1".equals(id)){
//请求转向
arg0.setAttribute("id", id);
System.out.println("没有使用重定向");
//请求转发
arg0.getRequestDispatcher("home.jsp").forward(arg0, arg1);
}else{
arg0.setAttribute("id", id);
System.out.println("使用重定向");
arg1.sendRedirect("home.jsp");
}
}
}
运行结果:
- 没有使用重定向
- 使用重定向
- 后台输出
注意:
- request作用域的数据再sendRedirect中不可见;session数据可见
- 再刷新时,forward的动作会反复执行;sendRedirect的上一次动作只执行1次,后1次动做重复执行;
- 查询用forward,增删改用sendRedirect;