概述
请求对象和响应对象,由服务器创建、管理、销毁,可以使用这两个对象进行浏览器的请求和客户端的响应
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//org.apache.catalina.connector.RequestFacade@4d3db504
System.out.println(request);
//org.apache.catalina.connector.ResponseFacade@4902387b
System.out.println(response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
请求和响应的过程
当服务器接收到请求会创建request对象和response对象,将请求消息封装到request对象中,将这两个对象作为参数传递给service方法,将响应消息封装到响应对象中,然后作出响应,过程结束后,两个对象都会被销毁
Response 响应
HttpServletResponse接口实现了ServletResponse接口以提供特定于HTTP的发送响应功能,Servlet容器创建HttpServletResponse对象(该类实现ServletResponse接口),并将该对象作为参数传递给Servlet的service方法(doGet、doPost等等)。
Response对象用于动态响应客户端请示,控制发送给用户的信息,并将动态生成响应。Response对象只提供了一个数据集合cookie,它用于在客户端写入cookie值。若指定的cookie不存在,则创建它。若存在,则将自动进行更新。结果返回给客户端浏览器。
重定向
重定向特点:
- 两次请求,两次响应
浏览器向服务器发送请求,服务器响应重定向状态码302,浏览器向百度发送请求,百度响应回页面 - 浏览器地址栏会发生变化
- 既可以跳转外部资源,也可以跳转内部资源
//设置此响应的状态代码
public void setStatus(int sc)
//用给定名称和值设置响应头。如果已经设置了头,则新值将重写以前的值。
//name:头的名称 value:头值
public void setHeader(String name, String value)
//使用指定重定向位置URL将临时重定向响应发送到客户端。
public void sendRedirect(String location) throws java.io.IOException
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应状态码
//302:响应状态码,重定向
response.setStatus(302);
//设置响应头,响应头名称location
//重定向可以用于页面跳转
response.setHeader("location","https://www.baidu.com");
/*跳转内部资源,home.jsp是项目中的一个页面
response.setHeader("location","/home.jsp");
内部资源也可以是Servlet,value值为完整的项目路径
response.setHeader("location","/demo1");*/
/*调用sendRedirect可代替以上重定向的两行代码
response.sendRedirect("/home.jsp");*/
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
响应文本信息到页面上
调用ServletResponse接口中的getWriter方法获取PrintWriter对象将文本信息写道页面上
//返回可将字符文本发送到客户端的PrintWriter对象。
public java.io.PrintWriter getWriter() throws java.io.IOException
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过response对象获取字符流
PrintWriter writer = response.getWriter();
//开发过程中用JSP来写响应的页面
writer.write("<h1 style='color:yellow'>");
//如果响应中文信息会发生乱码
writer.write("Hello Browser");
writer.write("</h1>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
解决中文响应信息乱码的问题
出现乱码的原因:浏览器和服务器使用的编码不一致
tomcat服务器默认采用的是ISO-8859-1编码,而浏览器没有这个编码
//设置将发送到客户端的响应的字符编码 (MIME charset)
public void setCharacterEncoding(String env) throws java.io.UnsupportedEncodingException
//设置将发送到客户端的响应的内容类型,如果该响应尚未提交。
public void setContentType(String type)
@WebServlet(name = "MyServlet3",value = "/demo3")
public class MyServlet3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置服务器的编码
response.setCharacterEncoding("utf-8");
//设置响应头,指定浏览器解码的编码
response.setHeader("content-type","text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<h1 style='color:yellow'>你好</h1>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
/*response.setCharacterEncoding("utf-8");
response.setHeader("content-type","text/html;charset=utf-8");
以上两行代码可以用以下代码代替*/
response.setContentType("text/html;charset=utf-8");
响应字节数据
响应字节数据,如图片、音频、视频等
web目录下的文件,浏览器可以直接访问;WEB-INF下的文件,浏览器不能直接访问,可以让浏览器请求后台来读取文件。
//返回适用于在响应中编写二进制数据的ServletOutputStream
//ServletOutputStream类提供用于将二进制数据发送到客户端的输出流
public ServletOutputStream getOutputStream() throws java.io.IOException
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取图片的真实路径
String realPath = this.getServletContext().getRealPath("/WEB-INF/a.png");
FileInputStream in = new FileInputStream(realPath);
//通过response对象获取输出流
ServletOutputStream out = response.getOutputStream();
int len=0;
byte[] bytes=new byte[1024];
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
}
in.close();
out.close();
//如果在Web项目中使用到第三方的jar包,在Web-INF目录下新建一个lib目录用于存放第三方jar包,记得要依赖jar包
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
Request 请求
HttpServletRequest接口实现了javax.servlet.ServletRequest接口,为HTTP Servlet提供请求信息。
Servlet容器创建HttpServletRequest对象,并将该对象作为参数传递给Servlet的service方法(doGet、doPost等等)。
Request对象作用是与客户端交互,收集客户端的Form、Cookies、超链接,或者收集服务器端的环境变量。客户端向服务器发出的请求,包括用户提交的信息以及客户端的一些信息。客户端可通过HTML表单或在网页地址后面提供参数的方法提交数据,然后服务器通过request对象的相关方法来获取这些数据。Request的各种方法主要用来处理客户端浏览器提交的请求中的各项参数和选项。
获取请求消息中的的数据
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求行中的数据
//获取请求方式
String method = request.getMethod();
//获取发出请求的URI
String requestURI = request.getRequestURI();
//获取发出请求的URL
StringBuffer requestURL = request.getRequestURL();
//获取GET请求中的请求参数
String queryString = request.getQueryString();
//获取协议的名称和版本
String protocol = request.getProtocol();
//获取发送请求的客户端的ip地址
String remoteAddr = request.getRemoteAddr();
//获取发送请求的客户端的端口号
int remotePort = request.getRemotePort();
//获取请求头中的数据
String host = request.getHeader("Host");
String header = request.getHeader("User-Agent");
System.out.println(host); // localhost:8080
System.out.println(header);
//获取请求的来源,可用于防盗链
String referer = request.getHeader("Referer");
System.out.println(referer); // http://localhost:8080/
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
获取请求参数
对于GET请求方式,可以调用getQueryString获取请求参数,对于POST请求方式,因为请求参数不在请求行中,所以要调用getReader方法获取输入流读取请求正文中的请求参数。
//使用BufferedReader以字符数据形式获取请求正文。读取器根据正文上使用的字符编码转换字符数据。
public java.io.BufferedReader getReader() throws java.io.IOException
//返回包含在请求URL中路径后面的查询字符串。如果URL没有查询字符串,则此方法返回null。
public String getQueryString()
//使用指定的编码机制对字符串解码
//s:要解码的字符串 enc:所支持的字符编码的名称
public static String decode(String s,String enc) throws UnsupportedEncodingException
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求参数的方法
getParameter(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
private void getParameter(HttpServletRequest request, HttpServletResponse response) throws IOException {
String queryString=null;
if (request.getMethod().equals("GET")){
queryString = request.getQueryString();
}else if (request.getMethod().equals("POST")){
queryString = request.getReader().readLine();
}
//使用"utf-8"对请求参数进行解码,否则如果参数存在中文,会出现乱码
queryString= URLDecoder.decode(queryString,"utf-8");
//如果参数存在中文,会出现乱码
System.out.println(queryString);
String[] split1 = queryString.split("&");
String[] split2 = split1[0].split("=");
String key=split2[0];
String value=split2[1];
System.out.println(key);
System.out.println(value);
String[] split3 = split1[1].split("=");
String key1=split3[0];
String value1=split3[1];
System.out.println(key1);
System.out.println(value1);
}
}
在实际开发中获取请求参数,调用request对象getParameter方法,通过键找值来获取请求参数
//以String形式返回请求参数的值,如果该参数不存在,则返回null。
public String getParameter(String name)
//重写此请求正文中使用的字符编码的名称。
public void setCharacterEncoding(String env) throws java.io.UnsupportedEncodingException
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求参数
//tomcat8.0以上GET请求中文不会出现乱码,所以我们只需要处理POST请求的中文乱码
//使用"utf-8"编码请求正文
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
获取表单中的请求参数
//返回包含给定请求参数拥有的所有值的String对象数组,如果该参数不存在,则返回null。
public String[] getParameterValues(String name)
<body>
<form action="/demo" method="post">
用户名:<input type="text" name="username"><br>
密 码:<input type="password" name="password"><br>
性别:
<input type="radio" name="gender" id="1" value="男" /><label for="1">男</label>
<input type="radio" name="gender" id="0" value="女" /><label for="0">女</label><br>
爱好:
<input type="checkbox" name="hobby" value="basketball" >篮球
<input type="checkbox" name="hobby" value="football" >足球
<input type="checkbox" name="hobby" value="tennis" >网球
<br>
学历:
<select name="edu">
<option value="senior">高中</option>
<option value="undergraduate">本科</option>
<option value="graduate">研究生</option>
</select>
<input type="submit" value="提交">
</form>
</body>
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
String gender = request.getParameter("gender");
String edu = request.getParameter("edu");
//获取复选框的请求参数要用数组接收
String[] hobbies = request.getParameterValues("hobby");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
可以在web.xml文件中配置开启项目后打开的页面
<!--默认打开index.jsp,可以通过该标签修改开启项目后打开的页面-->
<welcome-file-list>
<!--可以配置多个页面,如果第一个页面不存在,会去打开第二个页面,以此类推-->
<welcome-file>home.jsp</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
获取存放请求参数的集合
//返回此请求的参数的java.util.Map
public java.util.Map<K, V> getParameterMap()
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
@WebServlet(name = "MyServlet",value = "/demo")
public class MyServlet6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, String[]> parameterMap = request.getParameterMap();
Set<String> keySet = parameterMap.keySet();
for (String key : keySet) {
System.out.println(key+"..."+ Arrays.toString(parameterMap.get(key)));
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
获取请求参数所有的键,不常用
//返回包含此请求中所包含参数的名称的String对象的Enumeration。如果该请求没有参数,则此方法返回一个空的Enumeration。
public java.util.Enumeration<E> getParameterNames()
Request对象跳转页面
Request对象可以用于请求转发,来实现跳转页面
RequestDispatcher对象被用作包装位于特定路径上的服务器资源或通过特定名称给定的服务器资源的包装器,用于定义接收来自客户端的请求并将它们发送到服务器上的任何资源(比如Servlet、HTML文件或JSP文件)。
//返回一个RequestDispatcher对象,它充当位于给定路径上的资源的包装器。
public RequestDispatcher getRequestDispatcher(String path)
//将请求从一个Servlet转发到服务器上的另一个资源(Servlet、JSP文件或HTML文件)。
public void forward(ServletRequest request, ServletResponse response) throws ServletException, java.io.IOException
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "MyServlet1",value = "/demo1")
public class MyServlet1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//内部转发到demo2
request.getRequestDispatcher("/demo2").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "MyServlet2",value = "/demo2")
public class MyServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo2收到请求");
PrintWriter writer = response.getWriter();
writer.write("<h1>收到转发</h1>");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
请求转发,请求完成后,请求对象被销毁
特点:
- 一次请求,一次响应
浏览器向服务器发送请求,服务器响应请求的页面 - 地址栏不发生变化
- 只能跳转内部资源
请求转发与重定向的区别
- 请求转发的过程为一次请求,一次响应;而重定向的过程为两次请求,两次响应
- 请求转发时浏览器地址栏不发生变化;而重定向浏览器地址栏会发生变化
- 请求转发只能访问内部资源;而重定向还可以访问外部资源。如果内部资源位于WEB-INF目录下,重定向无法跳转资源,请求转发可以跳转
Request请求域对象
Request还是一个域对象,请求域对象,可以在一次请求响应间在多个资源之间共享数据
//存储此请求中的属性,在请求之间重置属性。此方法常常与RequestDispatcher一起使用
public void setAttribute(String name, Object o)
//以Object形式返回指定属性的值,如果不存在给定名称的属性,则返回null。
public Object getAttribute(String name)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "MyServlet1",value = "/demo1")
public class MyServlet4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int num=100;
request.setAttribute("num",num);
request.getRequestDispatcher("/demo2").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
@WebServlet(name = "MyServlet2",value = "/demo2")
public class MyServlet5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo2收到请求");
Integer num =(Integer) request.getAttribute("num");
System.out.println(num);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
注意:使用重定向无法获取请求域中的数据,因为重定向是两次请求,两次响应
请求路径的书写:
前台页面请求后台的路径,必须写上上下文路径
服务器内部跳转路径,不需要加项目上下文路径
重定向需要写上项目上下文路径
请求转发不需要写上项目上下文路径
//返回请求URI指示请求上下文的那一部分。请求URI中首先出现的总是上下文路径。路径以"/"字符开头但不以"/"字符结束。
public String getContextPath()
在实际开发中,一般调用getContextPath方法动态获取上下文路径