Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向容器输出数据,只需要找response对象就行了。
一 Response
1 常见方法
Response分为响应消息行,响应消息头和响应正文。对应Request分为请求消息行,请求消息头和请求正文。主要调用ServletResponse和HttpServletResponse类(接口)里的方法
2 常见作用
2.1 向客户端发送中文数据(解决乱码问题)
- 以字符流的形式响应(字符串文本数据)
response.getWriter().write(“中国”);//getWriter()返回Printwriter对象
接连出现??和涓浗的问题,原因如下:
由于Tomcat服务器中默认编码方式为ISO-8859-1,不支持中文。本身解析不了“中国“,所以在向浏览器响应结果时,出现??无法识别的情况(不是乱码),方法:setCharacterEncoding(“UTF-8”),告知服务器用UTF-8的方式解析文本。
然后,重新部署后,再次向浏览器响应结果时是“涓浗”(乱码),原因是没有告知浏览器应该用UTF-8的方式编码,方法:response.setHeader(“content-type”, “text/html;charset=UTF-8”)。
其实有个更简单的方法,直接告知服务器和浏览器均用UTF-8的方式编码,当然也可以用别的编码方式,格式:response. setContentType(“text/html;charset=UTF-8”);
- 以字节流的形式响应(二进制)
response.getOutputStream().write(“中国”.getByte());//以默认编码发送数据;getOutputStream()返回ServletOuputStream对象。
getByte(): String类中的方法,返回byte[];使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。(默认字符集就是你在安装操作系统时选择的安装语言,简体中文的编码方式是GBK)。
response.getOutputStream().write(“中国”.getByte(“UTF-8”));//以UTF-8编码向客户端发送数据,若浏览器默认GBK,会出现乱码(不一致而导致的乱码)。所以这时需要response.setContentType(“text/html;charset=UTF-8”);告知浏览器一声用UTF-8编码。
实例:
当response.setContentType(“text/html;charset=UTF-8”);
response.getOutputStream().write(“中国”.getByte());共同使用时,由于字节输出流使用默认编码(中文–GBK),不一致就会出现乱码。
注意:getOutputStream和getWriter这两个方法互相排斥,调用了其中的任何一个方法后,就不能再调用另一方法,否则会抛异常。
2.2 实现请求重定向
定义:一个web资源收到客户端请求后,(可能由于自身无法处理等问题)通知客户端去访问另外一个web资源,这称之为请求重定向。
特点:地址栏会变,并发送2次请求。
实现方式:
response.sendRedirect()
实现原理:
302/307状态码和location头即可实现重定
注意:sendRedirect的路径参数写法,是绝对路径还是相对路径(带不带”/”)?要不要写上应用名(项目名)?如果参数为”www.baidu.com“,允许这样写吗?会发生什么?要与后面的Request的请求转发方法RequestDispatcher()参数区分开。
response.sendRedirect("/day01/ResponseDemo4");//注意重定向时,不一定定向到哪个项目里去了,故需要在引号里写上/+项目名(应用名)。表示http//localhost:8080/后面的东西。当然也可以直接写"www.baidu.com",会跳转到百度界面
//sendRedirect本质上是下面方式的合并:
response.setStatus(302);//307也可以,都是告诉客户端要重新定向新的资源
response.setHeader("location", "/day01/ResponseDemo4");//发送响应消息头,告诉浏览器要去访问哪个URL。
3 Response重定向执行过程细节
- 客户端发送http请求给web服务器
- 若是首次访问,web服务器创建servlet(实例化,初始化);若不是,往下走(客户端访问同一个servlet,只初始化,实例化一次)。
- web服务器创建request和response对象。(初始时请求信息是有客户端传来的数据的,响应信息是空的)
- web服务器调用servlet的service(req,rep)方法。
- web把执行权交给servlet,先通过request获取请求信息(头,行,正文)。
- 然后执行程序,用sendRedirect方法,写特殊响应头,将结果保存到response对象中()
- servlet的service方法执行完毕,将执行权返回给web服务器。
- web服务器解析response对象返回值,发出包含重定向的http响应,返回给客户端。(web服务器=tomcat=servlet引擎)
- 客户端发送包含重定向的请求信息
- 然后又是一个轮回,只不过不用再创建servlet,而且执行权在servlet时,不用写特殊响应头,而是写真正的返回结果;另外web服务器返回不返回包含重定向的http响应,而是返回真正的结果。
二 Request
1 常用方法及含义
2 获取表单数据(Form)中文乱码问题
方法一:request.getParameter(name);
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
String[] hobbys = request.getParameterValues("hobby");
System.out.println(username);
for(int i=0;i<hobbys.length;i++){
System.out.println(hobbys[i]);
}
}
方法二:request.getParameterNames()
private void doGet(HttpServletRequest request)
throws UnsupportedEncodingException {
request.setCharacterEncoding("UTF-8");
Enumeration names = request.getParameterNames();
while(names.hasMoreElements()){
String name = (String)names.nextElement();
String values[]=request.getParameterValues(name);
for(int i=0;values!=null&&i<values.length;i++){
System.out.println(values[i]);
}
}
}
方法三:getParameterMap()
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
User u=new User();
Map <String,String[]> map=request.getParameterMap();
for(Map.Entry<String,String[]> m: map.entrySet()){
String key=m.getKey();
String value[]=m.getValue();
PropertyDescriptor pd=new PropertyDescriptor(key,User.class);//
Method setter=pd.getWriteMethod();
if(value.length==1){
setter.invoke(key, value[0]);
}
else{
setter.invoke(key, (Object)value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
3 请求转发
客户端发送请求后,服务器一个servlet无法完全处理,需要和另一个servlet协作,两者返回的结果共同响应给客户端。使用request.RequestDispatcher()方法,设置路径参数时要注意必须是绝对路径,而且只能是当前应用的servlet(类)。
- 客户端发送http请求
- 若是首次访问,servlet引擎实例化并初始化servlet,若不是直接到3
- servlet引擎创建请求request和响应response对象。
- servlet引擎调用service(req,rep)方法,传入刚创建的两个对象作为参数
- servlet引擎将执行权交给servlet,调用service里的doGet方法,获取请求信息
- servlet调用service方法中的doPost方法,写入响应信息
- servlet向servlet引擎返回请求转发forward命令(只能转发当前应用下的其他servlet、jsp等)
- servlet引擎收到forward命令后,找到请求转发地址(URI/Mapping),若是第一次访问,创建servlet2,并调用servlet2的service方法。
- servlet2读取请求信息
- 在原来响应信息基础上,追加信息的响应信息
- serlet2的service方法返回
- servlet的service方法返回
- servlet引擎解析响应信息
- servlet引擎返回响应结果给客户端
3.1 请求转发与重定向的区别
转发:地址栏不变;客户端只请求一次;servlet间可以传递数据;不可以跳转到其他应用。
重定向:地址栏变;客户端请求两次;不可以传递数据;可以跳转到其他应用。
4 请求包含
包含:Servelt(源组件)把其他web组件(目标组件)生成的响应结果包含到自身的响应结果中。
转发和请求包含的共同点
源组件和目标组件处理的都是同一个客户请求,源组件和目标组件共享同一个ServeltRequest和ServletResponse对象。
目标组件都可以为Servlet、JSP或HTML文档
都依赖 javax.servlet.RequestDispatcher接口