在 Servlet API 中,定义了一个 HttpServlet Request 接口,它继承自 ServletRequest 专门用来封装 HTTP 请求消息。由于 HTTP 请求消息分为请求行、请求消息头和请求消息体三部分,因此,在 HttpServlet Request 接口中定义了获取请求行、请求头和请求消息体的相关方法
当访问Servlet时,会在请求消息的请求行中,包含请求方法、请求资源名,请求路径等信息,为了获取这些信息,在 HttpServler Request 接口中,定义了一系列用于获取请求行信息的方法
public class GetHeader extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取http请求头消息中请求方式(get,post)
String method = request.getMethod();
System.out.println(method);//GET
//获取 URL 的主机和端口之后、参数部分之前 的部分
String requestURI = request.getRequestURI();
System.out.println(requestURI);// /RequestDemo/getheader
//GET 提交 url 地址后的参数字符串
String queryString = request.getQueryString();
System.out.println(queryString);// null
//获取 Servlet 的名称或 Servlet 所映射的路径
String servletPath = request.getServletPath();
System.out.println(servletPath);// /getheader
//获取访问者 ip 地址
String remoteAddr = request.getRemoteAddr();
System.out.println(remoteAddr);// 0:0:0:0:0:0:0:1
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
当请求 Servlet 时,需要通过请求头向服务器传递附加信息,例如,客户端可以接受的数据类型、压缩方式、语言等,为此,在 HttpServlet Request 接口中,定义了一系列用于获得HTTP 请求头字段的方法。
public class GetLine extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取 http 请求头的指定字段
String header = request.getHeader("User-Agent");
System.out.println(header);
//获取指定头的多个值
// request.getHeaders("User-Agent");
//获取一个包含所有请求头字段的 Enumeration 对象
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){
String nextElement = headerNames.nextElement();
String header2 = request.getHeader(nextElement);
System.out.println(nextElement+":"+header2);
}
//该方法用于获取Content_Length头字段的值, 结果为 int 类型
int contentLength = request.getContentLength();
System.out.println(contentLength);
//获取 ContentType 头字段的值,结果为 String 类型
String contentType = request.getContentType();
System.out.println(contentType);
// 获取消息实体部分字符编码
String characterEncoding = request.getCharacterEncoding();
System.out.println(characterEncoding);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
在实际开发中,经常需要获取用户提交的表单数据,例如,用户名、密码、电子邮件等,为了方便获取表单中的请求参数,在HttpServlet Request 接口中,定义了一系列获取请求参数的方法。
public class GetParam extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//获取指定名称的参数
String username = request.getParameter("username");
System.out.println(username);
// 如果有多个参数同名,可以使用此方法获取
String[] hobby = request.getParameterValues("hobby");
System.out.println(hobby);
// 获取所有参数对象
Enumeration parameterNames = request.getParameterNames();
while(parameterNames.hasMoreElements()){
System.out.println(parameterNames.nextElement());
}
//以键值对的形式获取参数
Map parameterMap = request.getParameterMap();
for (Map.Entryentry : parameterMap.entrySet()) {
System.out.println(entry.getKey());
for (String str : entry.getValue()) {
System.out.println(str);
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
上面的代码,如果输入的时中文字符,那么会产生乱码问题,如下图
是因为浏览器在传递请求参数时,默认采用 UTF-8 的编码,但是在解码时采用的是默认的ISO8859-1,因此导致控制台打印参数信息出现乱码
- 解决
在 Http ServletRequest 接口中,提供了一个 sctCharacterEncoding()方法,该方法用于设置 request 对象的解码方式
request.setCharacterEncoding(“UTF-8”);
此时就能解决问题
使用 sctCharacterEncoding()方法解决乱码问题只针对 POST 请求,而对 GET 请求是无效的,
为了解决 GET 方式提交表单的中文乱码问题,可以先使用错误码表 ISO8859-1 将用户名重新编码,然后使用码表 UTF-8 进行解码。
//get 方式乱码解决
String username = request.getParameter(“username”);//乱码
//先用 iso8859-1 编码 在使用 utf-8 解码
username = new String(username.getBytes(“iso8859-1”),”UTF-8”);
Reruest 对象不仅可以获取一系列数据,还可以通过属性传递数据,在 ServletRequest 接口中,定义了一系列操作属性的方法:
- setAttribute(key, value)
向 request 域中存入一个值(键值对形式)
getAttribute(key)
获取 request 域中指定键的值
removeAttribute()
删除 request 域中指定键的值
getAttributeNames()
获取域中所有
在 ServletI 中,如果当前 Web 资源不想处理它的访问请求,可以通过 forward()方法将当前请求传递给其他的 Web 资源进行处理,这种方式称为 请求转发。
- forward()方法工作原理
当客户端访问 Servlet1 时,可以通过 forward() 方法将请求转发给其它 Web 资源,其它Web 资源处理完请求后,直接将响应结果返回到了客户端0
相关方法介绍
request.getRequestDispatcher(path);
- 返回封装了某个路径所指定资源的 RequestDispatcher 对象
- 参数 path 必须以“/”开头,用于表示当前 Web 应用的根目录。
- WEB-INF 目录中的内容对 RequestDispatcher 对象也是可见的,因此,传递给
getRequestDispatcher(String path)方法的资源可以是 WEB-INF 目录中的文件
RequestDispatcher 接口方法介绍
forward(ServletRequest request, ServletResponse response)
- 该方法用于将请求从一个 Servlet 传递给另外的一个 Web
- 注意:该方法必须在响应提交给客户端之前被调用,否则将抛出IllegalStateException 异常
include(ServletRequest request,ServletResponse response)- 该方法用于将其它资源当做响应内容包含进来
public class Servlert1 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//向resquest域中存储数据
request.setAttribute("name", "lisi");
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet2");
requestDispatcher.forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
public class Servlet2 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Object attribute = request.getAttribute("name");
response.getWriter().write("hello:"+attribute);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
结果:
使用重定后,之前的 request 中存放的变量全部失效,并进入一个新的 request 作用域。
试音转发后,之前的 request 中存放的变量不会失效,就像把两个页面拼到了一起。
重定向两次请求,转发一次请求
重定向地址栏的地址变化,转发地址不变
重新定向可以访问外部网站,转发只能访问内部资源
转发的性能要优于重定向
怎么选择是重定向还是转发呢?通常情况下转发更快,而且能保持 request 内的对象,所以
他是第一选择。但是由于在转发之后,浏览器中 URL 仍然指向开始页面,此时如果重载当
前页面,开始页面将会被重新调用。如果你不想看到这样的情况,则选择转发。
ServletContext
创建:服务器启动
销毁:服务器关闭
域的作用范围:整个 web 应用
request
创建:访问时创建 request
销毁:响应结束 request 销毁
域的作用范围:一次请求中