Servlet_03
A.重定向
1.概述
浏览器请求服务器,服务器通过HTTP协议约定响应头去告诉浏览器,并实现请求
状态码:302
2.特点
a.两次请求,两次响应
b.地址栏会发生变化
c.可以跳转到外部站点资源,也可以跳转到内部站点的资源
3.方法
a.方式1
response.setStatus(302);设置状态码
response.setHeader("location", "网址");设置头,跳转外部网址
b.方式2response.setHeader("location", "内部文件");设置头,跳转内部资源
response.sendRedirect("跳转地址");
在浏览器请求地址,会发现,跳转到百度,并且地址栏发生变化package org.xxxx.demo; 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 Demo01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置状态码 response.setStatus(302); // 方式1 // 设置头 // response.setHeader("location", "http://wwww.baidu.com"); // 访问内部资源 /工程名/跳转的文件地址 // response.setHeader("location", "/MyServletDemo/index.jsp"); // 方式2 response.sendRedirect("http://www.baidu.com"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
跳转后
B.请求对象request
1.获取请求行
request.getMethod();获取请求的方式
request.getRequestURI();获取URI(其实就是个相对路径:工程名/虚拟地址)
request.getRequestURL();获取URL(全路径:http://ip/URI)
request.getProtool();获取协议版本
request.getRemoteAddr();获取ip
request.getRemoteHost();获取主机名
request.getRemotePort();获取端口
package org.xxxx.demo; 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 Demo01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取请求方式 String method = request.getMethod(); // 获取URI String uri = request.getRequestURI(); // 获取URL StringBuffer url = request.getRequestURL(); // 获取协议版本 String protocol = request.getProtocol(); // 获取ip String ip = request.getRemoteAddr(); // 获取主机名 String host = request.getRemoteHost(); // 获取端口 int port = request.getRemotePort(); System.out.println(method); System.out.println(uri); System.out.println(url); System.out.println(protocol); System.out.println(ip); System.out.println(host); System.out.println(port); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
2.获取请求头
request.getHeader("user-agent");获取请头的值(可以查看浏览器版本)
request.getDateHeader(name);获取日期头
request.getIntHeader(name);获取数字头
package org.xxxx.demo; 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 Demo01 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取请求头的值 String browser = request.getHeader("user-agent"); System.out.println(browser); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
3.处理请求(解决中文乱码)
处理表单提交后台的数据
a.处理get请求
get请求参数拼接在URL后面,通过getQueryString();获取请求参数
获取的是浏览器进行了一个URLEncode()编码后的值
要通过URLDecoder.decode();进行编码,否则会出现中文乱码
b.处理post请求
post请求把请求参数封装在请求体里面
通过request.getReader().readLine();获取
然后通过decode进行编码
c.验证
在index.jsp中写一个表单,提交用户名(中文)和密码
观察控制台获取的参数
index.jsppackage org.xxxx.demo; import java.io.IOException; import java.net.URLDecoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Demo01 extends HttpServlet { // get请求 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获取请求参数 中文会得到一个类似于%E5%BC%A0%E4%B8%89的乱码 String line = request.getQueryString(); // 通过decode进行编码 username=张三&password=123456 line = URLDecoder.decode(line, "utf-8"); // 获取信息 // 截取& String[] split = line.split("&"); // 截取=获取信息 String username = split[0].split("=")[1]; String password = split[1].split("=")[1]; System.out.println(username + "---" + password); } // post请求 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 从请求体中获取处参数 String line = request.getReader().readLine(); // 转码 username=张三&password=123456 line = URLDecoder.decode(line, "utf-8"); // 获取信息 // 截取& String[] split = line.split("&"); // 截取=获取信息 String username = split[0].split("=")[1]; String password = split[1].split("=")[1]; System.out.println(username + "---" + password); } }
<%@ 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="<%=basePath%>"> <title>My JSP 'index.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="styles.css"> --> </head> <body> <form action="/MyServletDemo/demo01" method="get"> <center> <input type="text" name="username" placeholder="请输入用户名" /><br> <input type="password" name="password" placeholder="请输入密码" /><br> <input type="submit" value="登录" /> </center> </form> </body> </html>
控制台结果
4.this.doGet()的由来
优化上一部的代码,将重复代码封装成一个方法
并且在判断是否是get/post的时候,也封装到方法中
这样一来,两个方法里都是调用方法,那在doPost()中调用doGet()即可
package org.xxxx.demo; import java.io.IOException; import java.net.URLDecoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Demo01 extends HttpServlet { // get请求 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { getParment(request, response); } // post请求 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } public void getParment(HttpServletRequest request, HttpServletResponse response) throws IOException { // 获取方式 String method = request.getMethod(); String line = null; if (method.equals("GET")) { // 获取请求参数 中文会得到一个类似于%E5%BC%A0%E4%B8%89的乱码 line = request.getQueryString(); // 通过decode进行编码 username=张三&password=123456 line = URLDecoder.decode(line, "utf-8"); } else if (method.equals("POST")) { // 从请求体中获取处参数 line = request.getReader().readLine(); // 转码 username=张三&password=123456 line = URLDecoder.decode(line, "utf-8"); } // 获取信息 // 截取& String[] split = line.split("&"); // 截取=获取信息 String username = split[0].split("=")[1]; String password = split[1].split("=")[1]; System.out.println(username + "---" + password); } }
5.获取参数
针对上面封装的方法,Java提供了获取参数的方法,我们只需要进行转码就行
a.request.getParameter(key);获取参数
b.request.setCharacterEncoding("utf-8");
request.setContentType("text/html;charset=utf-8");只能处理post
c.通过字符串方法转码(get和post方法通用)
getBytes("ISO-8859-1");解码
new String(bytes, "utf-8");编码
d.注意:
1)tomcat8.5版本,配置文件默认为utf-8
通过该方法获取参数的请求方式为get
则不需要转码,post需要转码
在不知道请求方式情况下,写方式b,只对post有效
2)低版本,配置文件默认为ISO-8859-1
通过获取post请求参数需要转码
获取get请求参数也需要转码
两个都需要转码,写方式c,对两者都有效
package org.xxxx.demo; import java.io.IOException; import java.net.URLDecoder; import java.util.Enumeration; 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 Demo01 extends HttpServlet { // get请求 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 转码1:只用于POST,适用于tomcat8.5版本 request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); // 获取参数 tomcat8.5版本,get方法不用转码 String username = request.getParameter("username"); String password = request.getParameter("password"); // 转码2:get/post方式通用,适用于tomcat低版本 // byte[] bytes = username.getBytes("ISO-8859-1"); // username = new String(bytes, "utf-8"); System.out.println(username + "---" + password); } // post请求 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
6.获取参数的四种方式
a.上一条中演示的
b.针对复选框(多选)
request.getParameterValues("hobby");
String[] values = request.getParameterValues("hobby"); for (String v : values) { System.out.println(v); }
c.拿到所有请求参数的键和值,封装到map集合(常用)
request.getParaterMap();
Map<String, String[]> map = request.getParameterMap(); // 遍历集合 Set<String> keySet = map.keySet(); // 遍历键 for (String key : keySet) { System.out.println(key); String[] values = map.get(key); // 遍历值 for (String v : values) { System.out.println(key + "===" + v); } }
d.获取迭代器,但多选只能获取的一个,所以不常用
Enumeration<String> names = request.getParameterNames(); while (names.hasMoreElements()) { String key = names.nextElement(); String v = request.getParameter(key); System.out.println(v); }
C.请求域
1.request
a.是一个请求对象,用来封装请求消息
b.是一个域对象,可以在他的范围内共享数据
c.请求的范围:一次请求和一次响应之间
2.请求转发
a.request.getRequestDispatcher("/mydemo").forward(request, response);
将当前请求转向1mydemo2,不用输入工程名
b.特点
1)一次请求一次响应
2)地址栏不发生变化
3)只能访问内部站点资源
c.什么时候使用重定向?什么时候使用转发?
1)如果需要在请求的多个资源中共享数据,则使用转发
2)如一次性的数据存入请求域中
d.代码
在Demo02中设置域对象,然后请求转发到Demo03
Demo02
package org.xxxx.demo; 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 Demo02 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 在请求域设置一个数据 request.setAttribute("num1", "100"); this.getServletContext().setAttribute("num2", "1000"); // 请求转发到/mydemo03 request.getRequestDispatcher("/demo03").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
Demo03
package org.xxxx.demo; 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 Demo03 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("收到mydemo02的转发请求"); // 获取域对象 String num1= (String) request.getAttribute("num1"); // 获取全局对象 String num2 = (String) this.getServletContext().getAttribute("num2"); System.out.println(num1); System.out.println(num2); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } }
在浏览器请求Demo02的地址
观察控制台输出的是Demo03的值
3.路径的书写
a.请求转发时,只用写/虚拟路径
b.重定向和网页上请求服务器时,要写/项目名/虚拟路径