Request对象:
问题:
浏览器发起请求到服务器,会遵循HTTP协议将请求数据发送给服务器。那么服务器接受到请求的数据该怎么存储呢?不但要存,而且要保证完成性。
解决:
使用对象进行存储,服务器每接受一个请求,就创建一个对象专门的存储此次请求的请求数据。
实现:
request对象
解释:
服务器接收到浏览器的请求后,会创建一个Request对象,对象中存储了此次请求相关的请求数据。服务器在调用Servlet时会将创建的Request对象作为实参传递给Servlet的方法,比如:service方法。
特点:
1.request对象有服务器创建
2.一次请求创建一个request对象
3.生命周期为一次请求内,请求结束即销毁此次请求的request对象
package com.bj.servlet;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* request对象学习之获取请求数据
* 请求数据:
* 请求行:请求方式 请求URL 协议
* getMethod(); 返回请求方式
* getRequestURL(); 返回请求URL
* getRequestURI(); 返回请求URI
* getQueryString(); 返回get请求中的URL中的用户数据 注意:post请求中没有此方法。
* getSchema(); 返回协议
* 请求头
* getHeader(String name) 根据键名获取请求头信息
* 注意:如果获取的请求头信息不存在返回null。
* getHeaderNames() 返回存储了请求头键名的枚举集合。
* 请求实体
* getParameter(String name) 根据键名获取数据
* 注意:
* 键名其实就是前端页面中的表单标签的name属性的值或者前端页面其他方式提交数据的键的名字
* 如果请求中没有对应的请求数据,则返回null.
* getParameterValues(String name) 根据键名获取同名不同的值,返回数组
* 注意:如果没有对应的键名,则返回null
* getParameterNames() 返回实体数据中键名的枚举
* 请求网络相关数据
* getRemoteAddr() 获取客户端的IP地址
* getRemotePort() 获取客户端端口号
* getLocalAddr() 获取服务器端的IP
* getLocalPort() 获取服务器端的端口号
*
*/
@WebServlet("/ReqServlet")
public class ReqServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求信息
//获取请求行信息
//获取请求方式
String method = req.getMethod();
System.out.println("请求方式:"+method);
//获取请求URL信息
StringBuffer requestURL = req.getRequestURL();
System.out.println("请求URL:"+requestURL.toString());
//获取请求URI信息
String requestURI = req.getRequestURI();
System.out.println("请求URI:"+requestURI);
//获取get请求URL中的请求数据
String queryString = req.getQueryString();
System.out.println("获取get请求URL中的数据:"+queryString);
//获取协议
String scheme = req.getScheme();
System.out.println("获取请求协议:"+scheme);
//获取请求头信息
//根据键名获取请求头信息
String header = req.getHeader("User-Agent");
System.out.println("获取浏览器版本信息:"+header);
//获取请求头中键名的枚举
Enumeration headerNames = req.getHeaderNames();
while(headerNames.hasMoreElements()){
//获取请求头键名
String name=(String) headerNames.nextElement();
//获取请求头的键名对应的值
String value=req.getHeader(name);
System.out.println(name+":"+value);
}
//获取请求实体数据(用户数据)
//根据键名获取数据
String uname = req.getParameter("uname");
String pwd=req.getParameter("pwd");
System.out.println("请求实体数据:"+uname+":"+pwd);
//获取同名不同值的实体数据
String[] favs = req.getParameterValues("fav");
if(favs!=null){
for(String s:favs){
System.out.println("fav的值为:"+s);
}
}
//获取请求实体中键名的枚举
Enumeration names = req.getParameterNames();
while(names.hasMoreElements()){
//获取键名
String name=(String) names.nextElement();
//判断
if("fav".equals(name)){
String[] favs2=req.getParameterValues(name);
if(favs!=null){
for(String s:favs2){
System.out.println(name+":"+s);
}
}
}else{
//获取值
String value=req.getParameter(name);
System.out.println(name+":"+value);
}
}
//请求相关的网络数据
//获取客户端信息
String remoteAddr = req.getRemoteAddr();
System.out.println("获取客户端的IP:"+remoteAddr);
//获取客户端的端口号(浏览器)
int remotePort = req.getRemotePort();
System.out.println("获取客户端的端口号:"+remotePort);
//获取服务器主机IP
String localAddr = req.getLocalAddr();
System.out.println("获取服务器IP:"+localAddr);
//获取服务器的端口号
int localPort=req.getLocalPort();
System.out.println("获取服务器端口号:"+localPort);
//处理请求信息
//响应处理结果
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
浏览器中输入如下内容来运行servlet:
![c75e2ece4e8a8c80bb28cea3ecd07281.png](https://img-blog.csdnimg.cn/img_convert/c75e2ece4e8a8c80bb28cea3ecd07281.png)
运行结果如下:
![8ecbac87228d2e98633a2e7d57e210b6.png](https://img-blog.csdnimg.cn/img_convert/8ecbac87228d2e98633a2e7d57e210b6.png)
Response对象:
问题:
在使用Request对象获取了请求数据并进行处理后,处理的结果如何显示到浏览器中呢?
解决:
使用Response对象
解释:
服务器在调用指定的Servlet进行请求处理的时候,会给Servlet的方法传递两个实参request和response。其中request中封存了请求相关的请求数据,而response则是用来进行响应的一个对象。
package com.bj.servlet;
import 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;
/**
*resp对象之处理响应学习:
* 设置响应行: 协议 状态码 状态消息
* resp.sendError(int status);
* 作用:可以自主的响应状态给浏览器
* 设置响应头
* addHeader(String name,String value) 添加响应头信息,同名数据不会覆盖
* setHeader(String nanme,String value) 设置响应头信息,会覆盖原有信息。如果没有此响应头则添加该信息。
* 设置响应实体(处理结果)
* resp.getWriter().write("实体内容");
* 注意:
* 实体内容可以分开进行响应。
* 注意:
* 一旦使用resp对象作出了请求响应,则意味着此次请求处理完毕。服务器在响应后会将此次请求相关的req对象和resp对象销毁。
*
*/
@WebServlet("/ResponseServlet")
public class ResponseServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求数据
//处理请求数据
//响应处理结果
//设置响应行
//自定义响应404异常
//resp.sendError(404);
//设置响应头
//添加响应头信息
resp.addHeader("mouse","thinkpad");
resp.addHeader("mouse","thinkpad2");
//设置响应头
//resp.setHeader("mouse", "two fly birds");
//设置响应实体
resp.getWriter().write("resp object");
resp.getWriter().write("resp object");
resp.getWriter().write("resp object");
resp.getWriter().write("resp object");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
![dd62af749655be39903cd434ad2824cb.png](https://img-blog.csdnimg.cn/img_convert/dd62af749655be39903cd434ad2824cb.png)
![6553339c26b9093e842cf903ee149c85.png](https://img-blog.csdnimg.cn/img_convert/6553339c26b9093e842cf903ee149c85.png)
代码修改如下:
//设置响应头
//添加响应头信息
resp.addHeader("mouse","thinkpad");
resp.addHeader("mouse","thinkpad2");
//设置响应头
resp.setHeader("mouse", "two fly birds");
结果如下:
![d8a904f0bef3aa65e4ace82d0f8e699d.png](https://img-blog.csdnimg.cn/img_convert/d8a904f0bef3aa65e4ace82d0f8e699d.png)
请求乱码问题解决:服务器获取的请求数据乱码
Get方式请求:
方式一:每个数据都要单独的进行转换
String uname = req.getParameter("uname");
String uname2 = new String(uname.getBytes("iso8859-1"),"utf-8");
方式二:
在doGet()方法中使用: req.setCharacterEncoding(“utf-8”);
在tomcat服务器目录下的conf文件下找到server.xml文件,打开进行如下配置:
![4e866c8a0ae19fe19366a7a1fbf531ea.png](https://img-blog.csdnimg.cn/img_convert/4e866c8a0ae19fe19366a7a1fbf531ea.png)
Post方式请求:
在doGet()方法中使用: req.setCharacterEncoding(“utf-8”);
响应乱码问题解决:浏览器中显示的服务器响应数据乱码
resp.setContentType("text/html;charset=utf-8");
流程总结:
Servlet的使用流程:
设置请求编码格式
设置响应编码格式
获取请求信息
处理请求信息
响应处理结果
数据流转流程:
浏览器------>服务器------->数据库
浏览器<------服务器<-------数据库
请求转发:
问题:
服务器在接收到浏览器的请求后,仅仅使用一个Servlet进行请求处理,会造成不同的Servlet逻辑代码冗余,Servlet的职责不明确。
解决:
使用请求转发。其实就是在一个servlet中调用其他的servlet。
特点:
1.降低了Servlet之间的代码冗余
2.一次请求转发内的Servlet共享此次请求request和response对象
3.浏览器9地址栏信息不改变。
req.getRequestDispather("请求转发的servlet的别名").forward(req,resp);
![d5aff474fefc3286f1a7209279fe2bb9.png](https://img-blog.csdnimg.cn/img_convert/d5aff474fefc3286f1a7209279fe2bb9.png)
Request对象作用域
问题:使用请求转发后,不同的Servlet之间怎么进行数据的共享呢?或者说数据怎么从一个servlet流转给另外一个Servlet呢?
解决:使用request对象的作用域
使用:
request.setAttribute(object name,Object value);
request.getAttribute(Object obj);
作用:解决了一次请求内的不同Servlet的数据(请求数据+其他数据)共享问题。
作用域:基于请求转发,一次请求中的所有Servlet共享。
注意:
使用Request对象进行数据流转,数据只在一次请求内有效。
特点:
服务器创建
每次请求都会创建
生命周期一次请求
重定向
问题:
如果当前的请求,Servlet无法进行处理怎么办?
如果使用请求转发,造成表单数据重复提交怎么办?
解决:
使用重定向
使用:
response.sendRedirect(“路径”);
本地路径为:uri
网络路径为:定向资源的URL信息
特点:
两次请求
浏览器地址栏信息改变
避免表单重复提交