• Servlet 学习(四)


    HTTP 响应的构成
    1、HTTP 响应行:

    • 协议、状态、描述
    • HTTP 1.1 中定义的状态代码

        100-199 是信息性代码,标示客户应该采取的其它动作
         200-299 表示请求成功
        300-399 表示那些已经移走的文件,常包括Location 报头,指出新的地址
        400-499 表示由客户引发的错误
        500-599 表示由服务器引发的错误

    2、HTTP 响应报头: (头部/首部/响应头)

    •  响应头和响应正文之间用空行分隔
    • 常用的响应报头

    3、HTTP 响应正文:

    • 响应正文可以是 HTML 、CSS 、 JavaScript 、TXT ....

        response.getWriter();

    • 响应正文可以是也可以是 二进制文件,比如 mp4 、mp3 、jpeg 、gif 、doc 、pdf

        response.getOutputStream();

    HttpServletResponse类型的对象

    1、基于HTTP 协议的请求响应机制的信息交换过程

    • 建立连接:

        客户端与服务器建立TCP 连接

    • 发送请求:

        建立连接后,客户端把请求消息发送到服务器的相应端口上

    • 处理请求

        Servlet 容器接受到HTTP 请求
        解析HTTP 请求并封装相应的对象

    • 发送响应:

        服务器在处理完客户端请求之后,要向客户端发送响应消息

    • 关闭连接:

        客户端和服务器双方都可以通过关闭Socket 来结束TCP/IP 对话

    2、与响应报头有关的方法:

    • void  setHeader( String name , String value ) 设置响应报头的通用方法
    • boolean  containsHeader( String name )  判断指定名称的响应报头是否存在,存在即返回true     
    • void addCookie( Cookie cookie )  在 响应报头中 添加 一个 Cookie ( 在 set-cookie 报头中追加一个 cookie 值 ,相当于 setHeader( "set-cookie" , value ))
    • void setContentType( String mimeType ) 相当于 setHeader( "content-type" , mimeType )
    • 常用的 MIME(Multipurpose Internet Mail Extension) 类型:

        application/octet-stream 未识别 或 二进制数据    application/pdf   PDF 文档
        video/mpeg    MPEG 视频文件              image/gif   动态图片
        image/jpeg  照片图片( .jpeg 、.jpg )           image/png   透明图片text/html   HTML文档
        text/plain  纯文本文档                  text/css   CSS样式
        text/javascript  JavaScript 脚本代码            text/xml  XML 文档
        text/json   JSON 格式的文本 ( JSON : JavaScript Object Notation )

    响应报头测试案例一:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Response</title>
    <style type="text/css">
        a {
            display: block ;
            width: 400px ;
            line-height: 50px ;
            border: 1px solid blue ; 
            margin: 10px auto ;
            text-align: center ;
        }
    </style>
    </head>
    <body>
    
        <a href="/Servlet/header/first"> First Header Servlet ( content type) </a>
        
        <a href="/Servlet/header/second"> Second Header Servlet ( refresh ) </a>
        
        <a href="/Servlet/image/show"> Show Image Servlet ( content dispositoin ) </a>
        
        <a href="/Servlet/image/down"> Download Image Servlet ( content dispositoin ) </a>
        
        <a href="/Servlet/status"> Response Status Servlet ( content dispositoin ) </a>
        
        <a href="/Servlet/redirect"> My Redirect Servlet ( content dispositoin ) </a>
        
    
    </body>
    </html>
    package ecut.response;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( urlPatterns= { "/header/first" , "/f" } )
    
    public class FirstHeaderServlet extends HttpServlet {
    
        private static final long serialVersionUID = -5880198269462470756L;
    
        @Override
        protected void service( HttpServletRequest request, HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" ); //设置响应的字符编码 (在服务器上起作用)
                    
            // 获得可以向客户端发送数据的输出流之前,就需要设置响应报头
            //response.setHeader( "content-type" ,  "text/html;charset=UTF-8" ); //设置响应正文的MIME(多任务因特网邮件扩充)类型
            response.setContentType( "text/html;charset=UTF-8" ); // 设置响应正文的 MIME 类型
            // 这里的 charset=UTF-8 用来告知 WEB 客户端 以何种编码处理接受到的 字符
            
            System.out.println( response.containsHeader( "content-type" ) );
            
            PrintWriter w = response.getWriter();
            // 发送响应正文
            w.println( "<div style='text-align:center ; border : 1px solid blue ; height : 400px ; width : 500px ; margin : auto auto ; '>" );
            w.println( "天天向上" );
            w.println( "</div>" );
            
        }
        
        
    
    }

    运行结果如下:

    控制台输出true,页面跳转到如下页面

    Servlet 3.0 开始允许使用注解来标注Servlet

    • @WebServlet在一个实现过Servlet 接口的类上标注,声明这是一个Servlet

        @WebServlet 的常用属性
          String name 指定当前Servlet 的名称,相当于xml 中的servlet-name
          String[] value 指定当前Servlet 对应的url (与url-pattern 对应)
          String[] urlPatterns 与value 作用相同
          int loadOnStartup 作用与load-on-startup ,设定Servlet 的加载顺序
          boolean asyncSupported 指定是否支持异步操作
          WebInitParam[] initParams 用于设置Servlet 初始化参数

    • @WebInitParam必须与@WebServlet 、@Filter 等联合使用,用于配置Servlet 或Filter 的初始化参数,等同于init-param。

        @WebInitParam 的属性
          String name : 用于设置初始化参数的名称
          String value : 用于设置初始化参数的值

    响应报头测试案例二:

    package ecut.response;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( value = { "/header/second" , "/s" , "/refresh" } )
    public class SecondHeaderServlet extends HttpServlet {
    
        private static final long serialVersionUID = -5880198269462470756L;
        
        private Date date = new Date();//只创建一次不要反复创建
        private DateFormat df = new SimpleDateFormat( "yyyy年MM月dd日 HH:mm:ss.SSS" );
    
        @Override
        protected void service( HttpServletRequest request, HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" ); // 设置 响应 的字符编码 (在服务器上起作用)
            
            // 动态获得当前 WEB 应用 的 路径 ( context path )
            String applicationPath = request.getContextPath() ;
            
            System.out.println( "applicationPath : " + applicationPath );
            //每3秒刷新一次
            //response.setHeader( "refresh" ,  "3,URL=" + applicationPath + "/refresh" );
            
            // response.setHeader( "refresh" ,  "3,URL=/Servlet/refresh" ); // 定时刷新
            
             response.setHeader( "refresh" , "3,URL=/Servlet/header/first"); // 定时跳转
            
            response.setContentType( "text/html;charset=UTF-8" ); // 设置响应正文的 MIME 类型
            
            PrintWriter w = response.getWriter();
            w.println( "<div style='text-align:center ; border : 1px solid blue ; height : 400px ; width : 500px ; margin : auto auto ; '>" );
            
            date.setTime( System.currentTimeMillis() );
            w.println( df.format( date ) );
            
            w.println( "</div>" );
            
        }
        
        
    
    }

    运行结果:

    3秒后跳转到first页面

    响应报头里设置 响应正文为二进制文件测试案例一:

    package ecut.response;
    
    import java.io.IOException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( "/image/show" )
    public class ShowImageServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1376233444161496825L;
    
        @Override
        protected void service(HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            
            response.setHeader( "content-type" , "image/jpeg" );
            
            // 响应报头 content-disposition 用来设置 响应正文中的二进制数据是 在浏览器显示 还是 由浏览器下载
            response.setHeader( "content-disposition" , "inline" );
            //Path接口表示一个目录或一个文件对应的路径(它可以定位本地系统中的一个文件或目录)
            //Paths类是一个工具类,其中定义了两个静态方法,专门用来返回Path对象:        
            //static Path     get(String first, String... more)转换的路径字符串,或一个字符串序列,当加入形成一个路径字符串, Path。 
            Path source = Paths.get( "D:/Koala.jpg" );
            //FileInputStream in = new FileInputStream( "D:/Koala.jpg" );
            
            // 获得可以向客户端发送二进制数据的字节输出流
            ServletOutputStream out = response.getOutputStream();
            // nio将 source 中的内容 "复制" 到 out 对应的输出流,实际上就完成了输出操作
            Files.copy( source, out ) ;
            
            /*
            byte[] bytes = new byte[32] ;
            int n ;
            while( ( n = in.read( bytes ) ) != -1 ){
                out.write( bytes ,  0 ,  n );
            }
            */
            
        }
        
        
    
    }

    运行结果:

    在浏览器中展示了响应的图片

    响应报头里设置 响应正文为二进制文件测试案例二:

    package ecut.response;
    
    import java.io.IOException;
    import java.net.URLEncoder;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet( "/image/down" )
    public class DownloadImageServlet extends HttpServlet {
    
        private static final long serialVersionUID = 448136179136896451L;
    
        @Override
        protected void service(HttpServletRequest request , HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" );
            
            String name = "Koala.jpg" ;
            
            Path source = Paths.get( "D:/" ,  name );
            
            response.setHeader( "content-type" , "image/jpeg" );
            
            // 响应报头 content-disposition 用来设置 响应正文中的二进制数据是 在浏览器显示 还是 由浏览器下载
            name = URLEncoder.encode( name , "UTF-8" ); // 如果文件名中含有汉字,则需要对汉字进行编码
            System.out.println( "编码后:" + name  );
            response.setHeader( "content-disposition" , "attachment;filename='" + name + "'" );
            
            // 获得可以向客户端发送二进制数据的字节输出流
            ServletOutputStream out = response.getOutputStream();
            // 将 source 中的内容 "复制" 到 out 对应的输出流,实际上就完成了输出操作
            Files.copy( source, out ) ;
            
        }
        
        
    
    }

    运行结果:

    对应目录下增加了相应的图片

    3、与响应状态有关的方法:

    • void  sendError( int statusCode , String statusMessage )

    响应状态测试案例一:

    package ecut.response;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet(  "/status" )
    public class ResponseStatusServlet extends HttpServlet {
    
        private static final long serialVersionUID = -7904861099406918294L;
    
        @Override
        protected void service( HttpServletRequest request, HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" ); 
            
            int statusCode = 404 ;
            String statusMessage = "这个Servlet是存在的,但是就是不让你访问" ;
            response.sendError( statusCode , statusMessage );
            //response.setStatus(statusCode); //效果不明显
    
            
            response.setContentType( "text/html;charset=UTF-8" ); 
            
            PrintWriter w = response.getWriter();
            w.println( "<div style='text-align:center ; border : 1px solid blue ; height : 400px ; width : 500px ; margin : auto auto ; '>" );
            w.println( "天天向上" );
            w.println( "</div>" );
            
        }
    
    }

    运行结果如下:

    响应状态测试案例二:

    package ecut.response;
    
    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;
    
    @WebServlet(  "/redirect" )
    public class MyRedirectServlet extends HttpServlet {
    
        private static final long serialVersionUID = -6205011155467276976L;
    
        @Override
        protected void service( HttpServletRequest request, HttpServletResponse response ) 
                throws ServletException, IOException {
            request.setCharacterEncoding( "UTF-8" );
            response.setCharacterEncoding( "UTF-8" ); 
            
            try {
                Thread.sleep( 5000 );
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            // 设置响应状态代码
            response.setStatus( 302 ); // 通知 WEB 客户端 需要打开另外的一个 "位置"
            // 设置 响应报头
            //response.setHeader( "location" ,  request.getContextPath() + "/pages/request/index.html" );
             response.setHeader( "location" ,  "http://www.baidu.com" );
            
            // response.sendRedirect( request.getContextPath() + "/index.html"  );
            
        }
    
    }

    302 命令浏览器链接到新的位置: sendRedirect( String url ),该方法会生成302 响应和Location 报头; url 可以是相对,也可以是绝对。

    运行结果如下:

    重定向达到百度页面
           

    转载请于明显处标明出处

    http://www.cnblogs.com/AmyZheng/p/8830801.html

  • 相关阅读:
    struts2_文件上传和下载
    struts2_方法拦截器
    struts2_Action之间的重定向传参
    struts2_全局的拦截器,拦截用户非法登陆
    Hibernate入门心得
    struts2_异常页面处理
    设计师小法器:字体大管家
    IE6,IE7下设置body{overflow:hidden;}失效Bug【转】
    子层的margintop属性应用到父层上的解决方法
    jQuery CSS选择器nthchild
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/8830801.html
Copyright © 2020-2023  润新知