Servlet第三篇(response;request)

response对象

Tomcat收到客户端的http请求,会针对每一次请求,分别创建一个代表请求的request对象、和代表响应的response对象
  那么我们获取浏览器提交过来的数据,找request对象即可。response对象代表http响应,那么我们向浏览器输出数据,找response对象即可。

什么是HttpServletResponse对象?
  http响应由状态行、实体内容、消息头、一个空行组成。HttpServletResponse对象就封装了http响应的信息。
HttpServletResponse的应用
  调用getOutputStream()方法向浏览器输出数据
    print
      Tomcat使用IOS 8859-1编码对其进行转换,“中国”根本对ISO 8859-1编码不支持。
    write
      "你好呀我是中国".getBytes()这句代码在转成byte[]数组的时候默认查的是gb2312编码,而"你好呀我是中国"支持gb2312编码,所以可以正常显示出来。

输出utf-8中文字符

getOutputStream().write(getBytes())

    • 设置头信息,告诉浏览器我回送的数据编码是utf-8的

  response.setHeader("Content-Type", "text/html;charset=UTF-8");

    • 使用meta标签模拟http消息头,告诉浏览器回送数据的编码和格式

  servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());

getwrite().write()

    • 使用getWriter()显示中文数据,只需要一个方法就搞掂了!

 response.setContentType("text/html;charset=UTF-8")(设置中文码表和浏览器)把response.setCharacterEncoding("UTF-8")(设置中文码表)的工作也做了

调用getWriter()方法向浏览器输出数据
  对于getWriter()方法而言,是Writer的子类,那么只能向浏览器输出字符数据,不能输出二进制数据

实现文件下载

    java的文件上传下载都是通过io流来完成的,既然要下载图片,首先要能够读取到它

    //获取到资源的路径
    String path = this.getServletContext().getRealPath("/download/1.png");

    //读取资源
    FileInputStream fileInputStream = new FileInputStream(path);

    //获取到文件名,路径在电脑上保存是\\形式的。
    String fileName = path.substring(path.lastIndexOf("\\") + 1);
  告诉浏览器,我要下载这个文件
    //设置消息头,告诉浏览器,我要下载1.png这个图片
    response.setHeader("Content-Disposition", "attachment; filename="+fileName);
    为了解决文件名乱码,我们要进行URL编码,代码如下:
    response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));

    将读取到的内容回送给浏览器
      //把读取到的资源写给浏览器
      int len = 0;
      byte[] bytes = new byte[1024];
      ServletOutputStream servletOutputStream = response.getOutputStream();

      while ((len = fileInputStream.read(bytes)) > 0) {
      servletOutputStream.write(bytes, 0, len);
      }

      //关闭资源
      servletOutputStream.close();
      fileInputStream.close();

实现自动刷新
  让浏览器实现自动刷新,那肯定又是修改消息头了。
  //每3秒自动刷新网页一次
  response.setHeader("Refresh", "3");

设置缓存
  浏览器本身就存在着缓存机制
  禁止缓存的功能
  //浏览器有三消息头设置缓存,为了兼容性!将三个消息头都设置了
  response.setDateHeader("Expires", -1);
  response.setHeader("Cache-Control","no-cache");
  response.setHeader("Pragma", "no-cache");

实现数据压缩
  GZIPOutputStream写数据的时候,是把数据写到ByteArrayOutputStream上的,等会还要把数据取出来,再写给浏览器
  //告诉浏览器这是gzip压缩的数据
  response.setHeader("Content-Encoding","gzip");
  生出随机图片
  要生成一张图片,java提供了BufferedImage类供我们使用
  //在内存中生成一张图片,宽为80,高为20,类型是RGB
  BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);

    //获取到这张图片
    Graphics graphics = bufferedImage.getGraphics();

    //往图片设置颜色和字体
    graphics.setColor(Color.BLUE);
    graphics.setFont(new Font(null, Font.BOLD, 20));

    //往图片上写数据,先写个12345,横坐标是0,纵坐标是20【高度】
    graphics.drawString("12345", 0, 20);
    把图片写给浏览器,java又提供了图片流【ImageIO】给我们使用
    //把图片传进去,类型是jpg,写给浏览器
    ImageIO.write(bufferedImage, "jpg", response.getOutputStream());

重定向跳转
  //重定向到index.jsp页面
  response.sendRedirect("/zhongfucheng/index.jsp");
  其实sendRedirect()方法就是对setStatus(302)和setHeader()进行封装,原理就是setStatus()和setHeader()
  getWriter和getOutputStream细节
  getWriter()和getOutputStream()两个方法不能同时调用。如果同时调用就会出现异常
  Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。
  Servlet的serice()方法结束后【也就是doPost()或者doGet()结束后】,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象.

request对象

什么是HttpServletRequest
  HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。
HttpServletRequest常用方法
 获得客户机【浏览器】信息
  getRequestURL方法返回客户端发出请求时的完整URL。
  getRequestURI方法返回请求行中的资源名部分。
  getQueryString 方法返回请求行中的参数部分。
  getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
  getRemoteAddr方法返回发出请求的客户机的IP地址
  getRemoteHost方法返回发出请求的客户机的完整主机名
  getRemotePort方法返回客户机所使用的网络端口号
  getLocalAddr方法返回WEB服务器的IP地址。
  getLocalName方法返回WEB服务器的主机名
 获得客户机请求头
  getHeader方法
  getHeaders方法
  getHeaderNames方法
 获得客户机请求参数(客户端提交的数据)
  getParameter方法
  getParameterValues(String name)方法
  getParameterNames方法
  getParameterMap方法

HttpServletRequest应用
  防盗链
    获取Referer这个消息头,判断Referer是不是从我的首页来的。如果不是从我的首页来的,跳转回我的首页。

String referer=request.getHeader("Referer");
if(referer== null||!referer.contains("http://localhost:8088/firstServlet/NewSvlt")){
response.sendRedirect("/firstServlet/NewSvlt");
return;

  表单提交数据【通过post方式提交数据】
    request.getParameter()
    request.getParameterValues()
  get方式提交数据
    通过超链接将数据带给浏览器
      <a href="/zhongfucheng/Servlet111?username=xxx">使用超链接将数据带给浏览器</a>

    sendRedirect()
      sendRedirect("servlet的地址?参数名="+参数值&"参数名=" +参数值);

  中文乱码问题
    首先我们来看一下post方法是怎么进行参数传递的。当我们点击提交按钮的时候,数据封装进了Form Data中,http请求中把实体主体带过去了【传输的数据称之为实体主体】,既然request对象封装了http请求,所以request对象可以解析到发送过来的数据,于是只要把编码设置成UTF-8就可以解决乱码问题了。

    而get方式不同,它的数据是从消息行带过去的,没有封装到request对象里面,所以使用request设置编码是无效的。
    Tomcat默认的编码是ISO 8859-1,那么get方式由消息体带过去给浏览器的时候肯定是用ISO 8859-1编码了

  •     手工转换

  Servlet第三篇(response;request)

  •     设置Tomcat

        在8080端口的Connector上加入 URIEncoding="utf-8",设置Tomcat的访问该端口时的编码为utf-8,从而解决乱码,这种改法是固定使用UTF-8编码的

      当然也有另一种改服务器编码的方式。设置Tomcat的访问该端口时的编码为页面的编码 useBodyEncodingForURI="true",这种改法是随着页面的编码而变。

  实现转发
    request的getRequestDispatcher.forward(request,response)实现转发

    (RequestDispatcher还有另外一个方法include(),该方法可以实现包含一般网页的头部和尾部是不需要改变的。如果我们多个地方使用Servlet输出网头和网尾的话,需要把代码重新写一遍。而使用RequestDispatcher的include()方法就可以实现包含网头和网尾的效果了。)

    request也可以称之为域对象,只不过ServletContext的域是整个web应用,而request的域仅仅代表一次http请求
  请求转发的细节
    如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常。 也就是说:不要在转发之前写数据给浏览器
    如果在调用forward方法之前向Servlet引擎的缓冲区中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。

  转发和重定向的区别
   实际发生位置不同,地址栏不同
    转发是发生在服务器的
    转发是由服务器进行跳转的,细心的朋友会发现,在转发的时候,浏览器的地址栏是没有发生变化的,在我访问Servlet111的时候,即使跳转到了Servlet222的页面,浏览器的地址还是Servlet111的。也就是说浏览器是不知道该跳转的动作,转发是对浏览器透明的。通过上面的转发时序图我们也可以发现,实现转发只是一次的http请求,一次转发中request和response对象都是同一个。这也解释了,为什么可以使用request作为域对象进行Servlet之间的通讯。
    重定向是发生在浏览器的
    重定向是由浏览器进行跳转的,进行重定向跳转的时候,浏览器的地址会发生变化的。曾经介绍过:实现重定向的原理是由response的状态码和Location头组合而实现的。这是由浏览器进行的页面跳转实现重定向会发出两个http请求,request域对象是无效的,因为它不是同一个request对象
   用法不同
    给服务器用的直接从资源名开始写(转发),给浏览器用的要把应用名写上(重定向)
   能够去往的URL的范围不一样
    转发是服务器跳转只能去往当前web应用的资源
    重定向是服务器跳转,可以去往任何的资源
   传递数据的类型不同
    转发的request对象可以传递各种类型的数据,包括对象
    重定向只能传递字符串
   跳转的时间不同
    转发时:执行到跳转语句时就会立刻跳转
    重定向:整个页面执行完之后才执行跳转

  转发和重定向使用哪一个?
    转发是带着转发前的请求的参数的。重定向是新的请求。
    典型的应用场景:
      转发: 访问 Servlet 处理业务逻辑,然后 forward 到 jsp 显示处理结果,浏览器里 URL 不变
      重定向: 提交表单,处理成功后 redirect 到另一个 jsp,防止表单重复提交,浏览器里 URL 变了

上一篇:hdu 1068 Girls and Boys 最大独立点集 二分匹配


下一篇:关于maven项目的servlet-api的问题