一.response.
1.response.characterEncoding和response.setContentType("text/html;charset=UTF-8"),response.setCharacterEncoding是设置服务器端输出的编码,而response.setContentType(),既指定了 服务器端的编码,又指定了浏览器端的编码.
2.常见的方法:

response.setStatus(int)://设置状态码,通常需要和响应头一起结合.例如302状态码和location一起结合等
response.setHeader/response.addHeader://当添加的两个响应头的键相同时,前者会覆盖,后者保留两个响应头.
response.setHeader("Refresh","2;URL=http://www.baidu.com");//设置响应头,2s后转向指定的URL
response.setHeader("Refresh","2");//每隔两秒刷新一次..
//下面的三个方法设置禁止浏览器使用缓存
response.setDateHeader("Expires",0);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");

3.在浏览器中模拟响应头(meta标签)
<meta http-equiv="Expires" content="0">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
注意web服务器发送的响应头字段的优先级比meta标签要高
4.response.getWriter方法和getOutPutStream方法:
1.两个方法不能同时使用.
2.response.getWriter方法返回的是PrintWriter对象,而response.getOutPutStream方法返回的是ServletOutPutStream对象.
3.可以用getOutPutStream方法输出字符,但是要先转化为字节数组,比较麻烦.
几个小细节:
1.response.getWriter()在一个service方法中进行多次调用,返回的是同一个对象,而response.getOutPutStream也一样.
2.response.getWriter()返回的PrintWriter的print方法和write方法几乎一样,print方法的底层实际上调用的就是write方法,唯一的区别就是如果要写入的字符为null,write会报异常,而print方法会写出null这个字符串

二.Request
1.如果在请求体中和get请求中包含同样的键,那么get请求中的值将会把请求体的值(post请求)给覆盖.
2.request.getParameter()方法一些需要注意的地方:
1.如果传递的参数不存在对应的键值对,返回null
2.如果传递的参数存在对应的键,但是键里没有赋值,那么返回空字符串
3.如果传递的参数存在对应的键,但是该键对应多个值,那么返回第一个匹配的字符串.想要将一个键对应的两个值都获取到用request.getParameterValues(name)
3.request.getRequestURI和request.getContextPath:
有一个URL:http://localhost:8080/day15_request1/DemoServlet1?username=14
request.getRequestURI:获取请求行中的资源部分,即位于URL的主机和端口之后,参数之前的部分.对上面的例子:/day15_request1/DemoServlet1
Request.getContextPath:获取用于获取请求请求URL中属于web应用程序的路径./day15_request1

4.request.getHeader(String name):获取指定名称的请求头,如果有多个获取第一个

request.getHeaderNames():获取所有请求头的键的枚举

 request.getHeaders(String name):获取指定名称的所有的请求头,返回的是枚举,记录了一个键所对应的多个值

三.请求包含和请求转发

1.请求包含

有以下几个细节需要注意:
1>.服务器不会去调整HttpServletRequest对象,因此HttpServletRequest对象依然保持的是初始的参数路径和信息.被包含者调用程序检测当前访问路径的时候,依然得到的是调用者的路径.
2>.被包含的如果是servlet程序,不能改变相应的状态码和状态头,如果它里面存在这样的语句,语句的执行结果将被忽略
3>.可以通过request.getQueryString获得整个查询参数,但是需要注意的是,如果在浏览器请求某个servlet的时候,没有携带参数,就算包含的时候携带了参数,这个方法也会返回null.但是如果在请求转发的getRequestDispatcher方法的括号内有参数,依然可以通过request.getParameter方法获取
4>.如果包含的是静态页面,Tomcat的缺省servlet会检查当前HttpServletResponse对象是否已经调用getWriter方法返回对象,如果已经调用就使用PrintWriter的write方法写出静态html的内容,如果没有调用,则会调用getOutPutStream方法的write方法直接写出到缓冲区中.因此就会存在一个问题:下面的代码会报错:

getServletContext().getRequestDispatcher("/a.html").forward(request,response);
response.getWriter().write("你在干嘛");

这是因为在缺省servlet中已经调用了getOutputStream了,而在这里又调用了getWriter方法,两个方法是冲突的.
此外输出html文件的时候可能会有意想不到的乱码问题.如果在请求转发到静态页面之前调用了getWriter方法,且没有指定content-type,那么就会用ISO8859-1对静态页面进行编码输出(这样子可能会乱码),否则直接将静态页面用流输出.
5>.RequestDispatcher接口封装了某个路径所指定的资源对象.注意:WEB-INF目录对RequestDispatcher接口是可见的.
6>.对于request.getRequestDispatcher()方法,如果请求转发的是html就读取文档发送到客户端,而如果请求转发的是jsp,就读取相应结果发送到客户端.因此,相当于缓冲区已经清空,结果已经提交给客户端,所以之后不能再调用include或者sendRedirect方法,这样会报错.
7>.RequestDispatcher对象只能包装当前web应用程序中的资源,所以forward和include方法只能实现一个web应用程序之间的转发请求和资源包含.
8>.在包含的时候,如果同时调用response.getWriter方法,实际上返回的对象是一样的,可以通过直接打印观察出来.
9>.请求包含jsp文件存在的问题:
1>>.乱码.如果不在请求的servlet处设置编码,那么jsp一定会发生乱码,因为jsp是动态资源,而且jsp中页面的内容是用response.getWriter写出的.因此为了防止jsp文件乱码,必须要在包含的servlet处设置编码!!!而html文件则不存在这种问题,因为DefaultServlet会直接将test.html文件按字节流原封不动的读取出来,再按字节流原封不动的写出.在客户端,会直接根据<meta>标签进行解析.
2>>.冲突.上面说过了JSP文件是调用response.getWriter()方法输出页面的,因此如果在包含的servlet处调用了response.getOutputStream方法,就会报错.

3>>jsp与普通静态页面的区别在于普通静态页面在请求的servlet处可以调用getOutPutStream方法,它会直接用字节流的形式进行输出(此时页面不能有getWriter方法)但是jsp只以getWriter形式输出,因此在转发jsp的时候,转发页面一定不能用getOutputStream方法.

2.请求转发.

1>.调用requestDispatcher().forward方法时,servlet容器将根据目标资源路径对当前HttpServletRequest对象中的请求路径和请求参数进行调整.例如下面的示例:

@WebServlet(name = "ForwardTestServlet", urlPatterns = "/ForwardTestServlet")
public class ForwardTestServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma","no-cache");
response.setContentType("text/html;charset=UTF-8");
request.getRequestDispatcher("/ForwardTestServlet2?name=hlhdidi").forward(request, response);
}
@WebServlet(name = "ForwardTestServlet2", urlPatterns = "/ForwardTestServlet2")
public class ForwardTestServlet2 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String uri=request.getRequestURI();
StringBuffer url=request.getRequestURL();
String query=request.getQueryString();
response.getWriter().write("uri="+uri+"<br>");
response.getWriter().write("url="+url+"<br>");
response.getWriter().write("query="+query);
}

输出结果:

如果是请求包含,将ForwardTestServlet中的forward改为Include,结果如下:

可以看出于请求包含对请求头不做出修改不同,请求转发对请求行做出了修改,也可以获取查询的参数了.
2.forward一个静态资源时候的过程:
如果在访问一个静态资源转发前,调用了getWriter方法,那么直接用getWriter的write方法写出这个静态资源,步骤是先将资源中的内容转化为字符文本后再输出.
如果没有调用,直接将静态资源的流传出去.(涉及getOutputStream方法)

3.在调用forward方法之前写入缓冲区的数据将会在调用forward方法的时候被清空,而在调用完forward方法之后写入的数据,将被忽略.这里注意,缓冲区清空这种情况只出现在请求转发中,而请求包含,在调用Include方法前和方法后都可以继续写数据且在页面正常相应.
4.在调用者程序中设置的响应状态码和响应头都不会忽略,而在被调用者程序中设置的响应状态码和响应头也不会忽略(和请求包含不同).被调用者相同的数据会把调用者的数据覆盖.

四.请求重定向和请求转发的比较

1.请求转发只能将请求转发给同一个web应用的组件而请求重定向可以转发到同一个站点上的其他web应用资源

2.请求重定向会改变浏览器显示的URL,而请求转发不会

3.请求转发调用者和被调用者共享同一个request和response,而请求重定向调用者和被调用者分别有自己的request和response.

4.无论是请求转发还是请求重定向都不能有内容已经被实际输出到了客户端.

servlet学习笔记_4的更多相关文章

  1. # jsp及servlet学习笔记

    目录 jsp及servlet学习笔记 JSP(Java Server Page Java服务端网页) 指令和动作: servlet(小服务程序) jsp及servlet学习笔记 JSP(Java Se ...

  2. Servlet学习笔记(四)

    目录 Servlet学习笔记(四) 一.会话技术Cookie.session 1. 什么是会话技术? 2. 会话技术有什么用? 3. Cookie 3.1 什么是Cookie? 3.2 使用Cooki ...

  3. Servlet学习笔记(三)

    目录 Servlet学习笔记(三) 一.HTTP协议 1.请求:客户端发送欸服务器端的数据 2.响应:服务器端发送给客户端的数据 3.响应状态码 二.Response对象 1.Response设置响应 ...

  4. Servlet学习笔记(二)

    目录 Servlet学习笔记(二) Request对象 1.request和response对象: 2.request对象继承体系结构: 3.什么是HttpServletRequest ? 4.Htt ...

  5. jsp&servlet学习笔记

    1.路径引用问题 一个css.jsp.html.或者javascript文件从从一个工程复制到另一工程,如果引用的时候使用的时相对路径,看似没有错误,但是却一直引用不进来,这时候要使用绝对路径,这样才 ...

  6. Servlet 学习笔记

    Servlet 运行在服务器上的 java 类: Servlet 容器为 javaWeb 应用提供运行时环境,负责管理 servlet 和 jsp 生命周期,以及管理他们的共享数据. 现在我们知道了 ...

  7. Servlet学习笔记(1)--第一个servlet&&三种状态对象(cookie,session,application)&&Servlet的生命周期

    servlet的404错误困扰了两天,各种方法都试过了,翻书逛论坛终于把问题解决了,写此博客来纪念自己的第一个servlet经历. 下面我会将自己的编写第一个servlet的详细过程提供给初学者,大神 ...

  8. Servlet学习笔记(七)—— 自己定义过滤器的编写改进:自己定义实现FilterChain

    笔记六中实现了三种过滤器:字符编码过滤.登录权限过滤.敏感词过滤,可是有个缺陷就是,限定了过滤顺序,而不能实现先进行request过滤.最后response过滤,而且中间几项过滤的顺序不能动态改变.所 ...

  9. Servlet学习笔记(八)—— 文件下载

    一.文件下载概述 比如图片或者HTML这类静态资源,仅仅要在浏览器中打开正确的网址就行下载.仅仅要资源放在应用程序文件夹或者其下的子文件夹中,但不在WEB-INF下.Servlet/JSP容器就会将资 ...

随机推荐

  1. 浅谈在静态页面上使用动态参数,会造成spider多次和重复抓取的解决方案

    原因: 早期由于搜索引擎蜘蛛的不完善,蜘蛛在爬行动态的url的时候很容易由于网站程序的不合理等原因造成蜘蛛迷路死循环. 所以蜘蛛为了避免之前现象就不读取动态的url,特别是带?的url 解决方案: 1 ...

  2. jQuery插件的开发之$.extend(),与$.fn.extend()

        jQuery插件的开发包括两种: 一种是类级别的插件开发,即给jQuery添加新的全局函数,相当于给jQuery类本身添加方法.jQuery的全局函数就是属于jQuery命名空间的函数,另一种 ...

  3. Python字符串格式化

    一.使用格式化符来格式化字符串: Python支持的所有格式化符 格式化符 意义 'd' 返回要格式化对象的十进制表示,如果可以 'i' 返回要格式化对象的十进制表示,如果可以 'o' 返回要格式化对 ...

  4. 渗透日记-POST注入

    今晚给一个网站做了一次入侵检测,首先进行信息刺探后,发现这个站有注入策略,所有页面都没法通过常规的注入,利用wvs扫描网站发现一个页面. 这个页面直接暴露出了错误信息,看了一下url没有参数却爆出了错 ...

  5. Redmine自定义字段增多后会变慢

    问题: 在Redmine部署使用后,发现更新事务时速度慢,进行了相关试验,去掉了可能影响速度的插件,仍然很慢.以下为对比试验: 1.包含12个自定义字段的项目,更新用时2136ms,记录如下: Sta ...

  6. Dynamics AX 2012 R2 如何处理运行时间较长的报表

    当处理的数据量较多,逻辑比较复杂时,报表可能会超时.为了解决这个问题,Reinhard一直使用SrsReportDataProviderPreProcess来做预处理报表.它会在调用SSRS前,在AX ...

  7. DragRow-GYF

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DragRowDemo.as ...

  8. WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常

    WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常 在wpf中封装Com组件时,调用组件 ...

  9. CSU 1660 K-Cycle(dfs判断无向图中是否存在长度为K的环)

    题意:给你一个无向图,判断是否存在长度为K的环. 思路:dfs遍历以每一个点为起点是否存在长度为k的环.dfs(now,last,step)中的now表示当前点,last表示上一个访问的 点,step ...

  10. day4总结

    函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过程或 ...