Request&Response

第一节 http请求协议

浏览器访问服务器几种方式:(常用get/post)
请求方式 请求说明
OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。
HEAD 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息
GET 向特定的资源发出请求(a href="servlet"标签/js location.href="servlet")
POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改
PUT 向指定资源位置上传其最新内容
DELETE 请求服务器删除Request-URI所标识的资源
TRACE 回显服务器收到的请求,主要用于测试或诊断
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
HTTP请求的数据详解

浏览器通过请求的协议,将数据发送给服务器.
请求协议三部分: 请求行,请求头,请求体。
请求行: 请求地址信息
请求头: 浏览器信息以请求头形式发送给服务器 : key:value (key固定)
请求体:用户数据

get请求:只有请求行和请求头 数据以请求资源地址?拼接形式传递给服务器的  没有请求体!
例如: http://192.168.21.100:8080/demo/aa?username=jack&password=1234
   <!-- get请求 -->

 

post请求,由请求行和请求头和请求体组成, 数据以请求体形式提交!
例如: http://192.168.21.100:8080/demo/aa
 <!-- post请求 -->

常见请求头汇总

请求头key 请求头value
referer 浏览器通知服务器,当前请求来自何处,如果是直接访问,则不会有这个头。常用于:防盗链
If-modified-Since 浏览器通知服务器,本地缓存的最后变更时间。与另一个响应头组合控制浏览器页面的缓存。
cookie 与会话有关技术,用于存放浏览器缓存的cookie信息。
user-agent 浏览器通知服务器,客户端浏览器与操作系统相关信息
connection 保持连接状态。Keep-Alive 连接中,close 已关闭
host 请求的服务器主机名
content-length 请求体的长度
content-type 如果是POST请求,会有这个头,默认值为application/x-www-form-urlencoded,表示请求体内容使用url编码
accept 浏览器可支持的MIME类型。文件类型的一种描述方式。
mime格式 浏览器请求数据的类型,例如: text/html ,html文件 text/css,css文件 text/javascript,js文件 image/*,所有图片文件
accept-encoding 浏览器通知服务器,浏览器支持的数据压缩格式。如:GZIP压缩
accept-language 浏览器通知服务器,浏览器支持的语言。各国语言(国际化i18n)

第二节 HttpServletRequest对象request学习

  • 通过request的api我们可以获取浏览器发送的请求行的数据

  1. String getMethod() 获取请求方式的类型
  2. String getRequestURI() 获取请求行中的资源名部分
  3. StringBuffer getRequestURL() 获取客户端发出请求完整URL
    说明: uri: 统一资源标识符,用来标识一个资源,资源路径。(相当于身份证) url: 统一资源定位符,是一种具体的URI,可以用来标识一个资源.并且指明了如何定位一个资源.(相当于身份证中的地址)
  4. String getProtocol() 获取当前协议的名称和版本
  5. String getRemoteAddr() 获取IP地址6. int getLocalPort() 获取端口
  • 请求头的组成元素(通过request获取请求头信息)

@WebServlet(name = "DemoServlet2",urlPatterns = "/demo2")
public class DemoServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws
                        ServletException, IOException {
        doGet(request,response);
}
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
                ServletException, IOException {
        /**
        * 1. String getHeader(String name)
        以 String 的形式返回指定请求头的值
        * */
        String header = request.getHeader("User‐Agent");
        System.out.println("getHeader:"+header);
        System.out.println();
        /**
        * 2. Enumeration getHeaderNames()
        返回此请求包含的所有头名称的枚举
        * */
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()){
        System.out.println("getHeaderNames:"+headerNames.nextElement());
     }
    }
} 
测试结果: 
getHeader:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/63.0.3239.132 Safari/537.36    
getHeaderNames:host
getHeaderNames:connection
getHeaderNames:cache‐control
getHeaderNames:user‐agent
getHeaderNames:upgrade‐insecure‐requests
getHeaderNames:accept
getHeaderNames:accept‐encoding
getHeaderNames:accept‐language
getHeaderNames:cookie
  • Request接收请求数据(***)

方法名 描述
String getParameter(String name) getParameter获得指定参数名对应的值。如果没有返回null,如果只有多个获得第一个。 例如:username=jack
String[] getParameterValues(name) getParameterValues[] 获取请求数据key相同的多个数据
/**
 *   方法封装  类封装  原子性   单一 原则
 */
@WebServlet("/requestServlet")
public class RequestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");//  获取用户提交用户名信息
        String[] hobbies = request.getParameterValues("hobby");//
        System.out.println("用户名 = "+username);
        System.out.println("兴趣爱好:"+ Arrays.toString(hobbies));

    }
}
  • Request的其他作用 (*)

String getContextPath() 获取应用程序名称
通常情况,工程名称=发布的应用程序名称。
如果应用程序名称发生改变,那么我们如何获取呢? 通过getContextPath()可以获取发布的应用程序名称。

第三节 HttpServletResponse对象response学习

状态码:服务器与浏览器用于确定状态的固定数字号码,数字用来表示服务器针对请求做出的响应的状态,常见的响应状态码:

    302 Move temporarily 重定向,请求的资源临时从不同的 URI响应请求。

    304 Not Modified 从缓存中读取数据,不从服务器重新获取数据

    404 :请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。
    
    403 Forbidden 服务器已经理解请求,但是拒绝执行它
    
    405 Method Not Allowed 请求行中指定的请求方法不能被用于请求相应的资源

    500 :服务器内部错误。通常程序抛异常。
  • 响应头 (key:value形式)

响应头Key 响应头value
location 指定响应的路径,需要与状态码302配合使用,完成跳转。
content-Type 响应正文的类型(MIME类型)例如:text/html;charset=UTF-8
content-disposition 通过浏览器以附件形式解析正文,例如:attachment;filename=xx.zip
set-cookie 与会话相关技术。服务器向浏览器写入cookie
content-encoding 服务器使用的压缩格式,例如:gzip
content-length 响应正文的长度
refresh 页面刷新,例如:3;url=www.itcast.cn //三秒刷新页面到www.itcast.cn
server 指的是服务器名称,默认值:Apache-Coyote/1.1
last-modified 服务器通知浏览器,文件的最后修改时间。与If-Modified-Since一起使用。

Response常见方法:

addCookie(Cookie cookie):这个方法是向Response容器中添加一个Cookie,然后服务器容器会自动的将这个Cookie回写给客户机的,至于Cookie的相关知识我们会在后面的文章中进行详解,这篇文章中这个方法暂时用不到。

addDateHeader(String name ,long date):这个是向客户机添加一个时间值属性的响应头信息,比如那个缓存的响应头expires

addHeader(String name,String value):这个是向客户机添加一个字符串值属性的响应头信息,比如重定向的响应头location

addIntHeader(String name ,int value):这个是向客户机添加一个字符串属性的响应头信息

containsHeader(String name):这个方法是判断是否含有这个响应头信息字段

encodeURL(String name):这个方法是用于url改写的功能的,这个和session有关,等到说session那篇文章的时候在详细说明

sendRedirect(String name):这个方法是用于请求重定向的,和响应头中的location字段的作用相同

setHeader(String name,String value)/setIntHeader(String name,int value)/setDateHeader(String name,long date):这些方法和addHeader方法是相对应的,唯一和addHeader不同的是,addHeader是向Response中添加一个响应头信息,而setHeader是修改一个响应头信息的。

setStatus(int value):通过这个方法是设置响应码的,比如:200,304,404等。

getOutputStream():通过这个方法可以拿到一个字节流,然后可以向Response容器中写入字节数据,最后客户机向Response容器中拿去数据进行显示

getWriter():通过这个方法可以拿到一个字符流(PrintWriter),然后可以向Response容器中写入字符数据,最后客户机向Response容器中拿去数据进行显示

setContentLength():通过这个方法设置服务器向用户返回的数据长度,我们在HTTP协议详解这篇blog中的那个压缩数据的返回的例子中有说到

setContentType():方法可以直接设置响应头content-type的内容
  • 转发和重定向的区别

1. 转发在一次请求中完成,重定向是两次请求
2. 转发操作发生在服务器内部,重定向是浏览器执行操作
3. 转发地址栏不变(只有一次请求,一个地址),重定向,地址栏变化(两次请求,两个地址)
4. 转发可以在一次请求中共享数据,重定向不行(重定向两次请求)
1530781134215.png
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("utf-8");
        //  1. 只对post提交数据有效 请求体数据有效 2.必须要request.getParameter之前执行

        //  1.获取用户名和密码
        response.setContentType("text/html;charset=utf-8");//  text/plain  .txt  text/xml  xml   text/html   text/json  ajax
        //  获取输出流 向浏览器发送数据
        PrintWriter out = response.getWriter();
        String name = request.getParameter("name");
        String password = request.getParameter("password");
        System.out.println("用户名 = " + name);
        //  2.访问数据库
        String sql = "select * from users where name = ? and password = ?";
        JdbcTemplate template = new JdbcTemplate(C3p0Utils.getDataSource());
        User existUser = null;
        try {
            //  单一原则  查不到对象template报运行错误
            existUser = template.queryForObject(sql, new BeanPropertyRowMapper(User.class), name, password);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        //  3. 查询结果   转发和重定向处理
        if (existUser == null) {
           //  response.sendRedirect("login.html");
            //  转发完成登录错误 信息提示    request绑定一个错误信息  key  login_error
            request.setAttribute("login_error","账号或密码错误");
            //  跳转到显示登录错误信息的servlet
        request.getRequestDispatcher("/loginErrorServlet").forward(request,response);
        } else {
//        response.setStatus(302);
//  服务器发送给浏览器状态码 302  浏览器接受302  向location地址发送新的请求
//        response.setHeader("Location","index.html");
// 这行代码相当于上面两行
            response.sendRedirect("index.html");
        }
    }
}
@WebServlet("/loginErrorServlet")
public class LoginErrorServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //  登录错误显示处理
        PrintWriter out = response.getWriter();
        out.print("");
        String errorinfo = (String)request.getAttribute("login_error");
        //  request绑定错误信息获取
        out.print(""+errorinfo+"");
        out.print("");
        out.print("用户名
"); out.print("密码
"); out.print(""); out.print(""); out.print(""); } }

案例-Response对象完成下载服务器资源

  • 关于工程目录结构的说明


    工程目录结构.PNG
@WebServlet(name = "loadServlet", urlPatterns = "/loadServlet")
public class LoadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //获取浏览器提交过来的文件名
        String filename = request.getParameter("filename");
        //获取服务器资源位置 : 通过ServletContext对象    一个流两个头:附件弹窗头/文件类型头
        ServletContext servletContext = getServletContext();
        //获取资源的绝对路径
        String realPath = servletContext.getRealPath("/WEB-INF/"+filename);
        //创建文件对象,如果对象存在,那么则输出
        File file = new File(realPath);
        if(file.exists()){
            //设置响应头"下载附件弹窗"
           //  attachment 附件形式   inline 浏览器直接打开的资源
            response.setHeader("content-disposition","attachment;filename="+filename);
            // 根据文件名扩展名 获取文件对应的Mime类型  然后将文件类型告诉response
            String mime = servletContext.getMimeType(filename);
            response.setContentType(mime);
            //创建一个response的输出流
            ServletOutputStream os = response.getOutputStream();
            //创建文件的输入流 内存->程序
            InputStream in = new FileInputStream(file);
            int len = -1;
            byte[] bytes = new byte[1024*4];
            while((len=in.read(bytes))!=-1){
                os.write(bytes,0,len);
            }
            in.close();
        }
    }
关于下载时文件名乱码的处理
 response.setHeader("Content-Disposition","attachment;filename="+new String(filename.getBytes("gbk"), "ISO8859-1"));

你可能感兴趣的:(Request&Response)