Servlet请求与响应、ServletContext对象

目录

  • 关于HTTP1.1
      • 概述
      • 请求部分
      • 响应部分
  • Request和Response
      • Request部分
      • Response部分
  • ServletContext
      • 基本概述



关于HTTP1.1

概述

HTTP(HyperText Transfer Protocol)超文本传输协议,是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)
请求:客户端发送给服务器端的数据
响应:服务器端发送给客户端的数据

请求部分

请求基本结构

一个完整的由客户端发送给服务器的HTTP请求中包含以下的完整数据:
1.请求行:请求方式、资源路径、使用的协议以及版本号GET/monkey.html HTTP/1.1
2.多个请求头:对客户端环境描述、客户端请求的主机地址等信息
Accept - - 浏览器可接收的MIME类型,即文件内容类型
Accept-Charset - - 告知服务器客户端支持的字符集
Accept-Encoding - - 浏览器能够进行解码的数据编码方式
Accept-Language - - 浏览器支持的语言
Connection - - 是否需要持久连接
Cookie - - 会话相关
Referer - - 当前页面从哪个页面访问过来的
3.请求空行:空行,分隔
4.请求体:内容正文(GET没有请求体,POST有请求体)

请求状态码

状态码 英文名称 描述
200 OK 请求成功
400 Bad Request 客户端请求的语法错误,服务器无法解析
404 Not Found 服务器无法根据客户端的请求找到资源
500 Internal Server Error 服务器内部错误,无法完成请求
GET请求

  • 请求网址:http://localhost:8080/monkey.html?username=monkey&password=111
  • 请求参数信息全部在请求行中,请求的数据全部在浏览器的地址栏,在url后,请求的url长度有限制,不安全
  • 参数连接:资源?参数名=参数值&参数名=参数值&…
POST请求

  • 请求网址:http://localhost:8080/monkey.html
  • 请求参数在请求体中,请求的数据不会出现浏览器的地址栏,请求的url长度没有限制,安全
GET和POST请求的区别

  • GET请求数据在浏览器的地址栏,而POST不会出现。故POST比GET更安全
  • POST请求的参数存放于请求体中,而GET存放于请求行中
  • GET请求URL长度有限制(上限2K),而POST没有限制。文件上传时使用POST方式
  • GET可以缓存,POST不能缓存
什么情况下选择GET或POST请求

  • 传递大量数据,上传文件用POST
  • 机密信息用POST,因为POST安全性比GET高
  • 仅仅是索取数据,使用GET
  • 增加、修改、删除数据,使用POST

响应部分

响应基本结构

客户端向服务器发送请求,服务器应当做出响应,将数据返回给客户端
一个完整的由服务器发送给客户端的HTTP响应中包含以下的完整数据:
1.响应行:HTTP协议版本、状态码、状态英文名 如HTTP/1.1 200 OK
2.多个响应头:对服务器的描述、对返回数据的描述(以下只举例部分)
Location - -
Server - - 服务器名称
Content-Encoding - - web服务器支持返回内容压缩编码类型
Content-Type - - 服务器告诉客户端本次响应体数据格式以及编码格式,text/html;charset=UTF-8
Transfer-Encoding - - 文件传输编码
Refresh - - 定时刷新
Set-Cookie - - 设置HTTP Cookie
3.响应空行:空行
4.响应体:传输的数据

响应状态码

常见的200 - -成功;303 - - 重定向;400 - -Not Found,500 - - 服务器内部错误;405 - -没有对应的doGET或者doPost方法
状态码 描述
1** 信息,服务器收到请求,需要客户端继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误

参考文档:HTTP状态码参考文档




Request和Response


Request部分

request体系结构

ServletRequest接口 - - 请求对象,封装了获取所有请求信息,如请求行、请求头、请求实体
HttpServletRequest接口 - - 继承了 ServletRequest接口,用于处理HTTP协议请求的方法

Servlet请求与响应、ServletContext对象_第1张图片

HttpServletRequest常用方法

获取请求行数据 GET /MyItems/demo2?username=monkey HTTP/1.1

  • String getMethod() - - 返回请求方式(GET/POST)
  • String getContextPath() - - 返回虚拟目录,如/MyItems
  • String getServletPath() - - 返回servlet的路径,如/demo2
  • String getQueryString() - - 返回get方式请求参数,如
  • String getRequestURI() - - 返回请求行中资源名字 username=monkey
  • String getRequestURI() - - 返回请求URI,如/MyItems/demo2,URI(统一资源标识符,范围比URL大)
  • StringBuffer getRequestURL() - - 返回请求URL,如http://localhost/MyItems/demo2 ,URL(统一资源定位符)
  • String getProtocol() - - 返回协议版本,如HTTP/1.1
  • String getRemoteAddr() - - 返回请求服务器的客户端IP地址

获取请求头

  • String getHeader(String name) - - 根据指定的请求头获取对应的请求头值,如Host、Connection、User-Agent等等

获取请求体数据(注:只有POST请求方式才有请求体)
1.先获取流对象

  • BufferedReader getReader() - - 获取字符输入流,只能操作字符数据
  • ServletInputStream getInputStream() - - 获取字节输入流,可以操作所有类型数据(可用于文件上传)

2.再从流对象中取数据
例如,从登陆表单中获取数据,返回username=monkey&password=111

/*POST or GET*/
 BufferedReader br = request.getReader();
 String line = null;
 while((line = br.readLine())!= null){
     System.out.println(line);
 }

获取请求参数(GET和POST都能使用)

  • String getParameter(String name) - - 根据参数名称获取对应参数值,如传username获取值monkey
  • String[] getParameterValues(String name) - - 根据参数名称获取该参数的多个值,返回的是数组,一般是复选框
  • Enumeration getParameterNames() - - 获取所有请求参数的名称,如username、password、age等等,返回枚举类型
  • Map< Sting ,String[]> getParameterMap() - - 返回请求参数组成的Map集合,即键值对

解决中文乱码问题

Servlet请求与响应、ServletContext对象_第2张图片

//设置流的编码
request.setCharacterEncoding("utf-8");

案例:获取用户提交的内容

<body>
  <form action="/demo6" method="post">
      用户名:<input type="text" name="username"><br>
      密码:<input type="password" name="password"><br>
      爱好:<input type="checkbox" name="hobby" value="逛街">逛街
      <input type="checkbox" name="hobby" value="蹦迪">蹦迪
      <input type="checkbox" name="hobby" value="购物">购物
      <input type="checkbox" name="hobby" value="游戏">游戏
      <br>
      <input type="submit" value="注册">
form>
body>
public class RequestDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("username");
        String password = request.getParameter("password");
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("用户名:"+name);
        System.out.println("密码:"+password);
        System.out.print("爱好:");
        for(int i = 0;i < hobbies.length;i++){
            System.out.print(hobbies[i]+" ");
        }
        System.out.println();
    }

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

    }
}
请求转发

一种在服务器内部的资源跳转方式,从Servlet1请求转发到Servlet2,Servlet完成一部分功能再跳转到Servlet2继续完成Servlet1不能完成的功能

 request.getRequestDispatcher(String Path).forward(request,response);
 //
 参数:
 Path - - 表示跳转的目标资源路径,不能是当前服务器以外的资源路径,如百度,csdn等等
/*浏览器这里是GET请求,但是我在GET里面调用POST封装请求和响应对象,最终是由POST输出*/
/*从RequestDemo1请求转发到RequestDemo2*/
@WebServlet("/demo7")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("这里是request的POST demo7");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }
}

@WebServlet("/demo6")
public class RequestDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo6这里执行了");
        request.getRequestDispatcher("/demo7").forward(request,response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

转发特点 - - forward

  • 浏览器地址栏路径不发生变化
  • 只能转发到当前服务器下的资源路径,不能是当前服务器以外的资源,如百度、csdn等
  • 请求转发只发送一个请求
共享数据

域对象 - - 一个有作用范围的对象,可以在范围内共享数据
request域 - - 代表一次请求的范围
作用域对象如何共享数据?

  • void setAttribute(String name,Object obj) - - 设置作用域中的共享数据
  • Object getAttribute(String name) - - 通过键获取值
  • removeAttribute(String name) - - 通过移除键值对
/*RequestDemo1和RequestDemo2 设置和获取 共享数据 */
/*输出obj的结果为monkey*/
@WebServlet("/demo7")
public class RequestDemo2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Object obj = req.getAttribute("v");
        System.out.println(obj);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }
}

@WebServlet("/demo6")
public class RequestDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("v","monkey");
        request.getRequestDispatcher("/demo7").forward(request,response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}



Response部分


HttpServletResponse常用方法

ServletResponse接口 - - 响应对象,封装了获取所有响应消息(状态行,响应头,请求实体)的方法
HttpServletResponse接口 - - 继承了ServletResponse接口,处理HTTP协议响应的方法

设置响应消息—普通方法

  • setHeader(int sc) - - 设置状态码
  • setHeader(String name,String value) - - 设置响应头

设置响应体
获取输出流(字符输出流or字节输出流)->使用输出流,将数据输出到客户端浏览器
字符输出流 - - PrintWriter getWriter()
该方法获取的字符输出流对象为PrintWriter类型,可直接输出字符文本内容,若想要输出内容全为字符文本的网页文档,可使用getWriter()方法

字节输出流 - - ServletOutputStream getOutputStream()
该方法获取的字节输出流对象为ServletOutputStream类型,是OutputStream的子类,可以直接输出字节数组中的二进制数据。若想要输出二进制格式的响应正文,就使用getOutputStream()方法,如文件下载

/*使用字节输出流来输出纯文本数据*/
 resp.setContentType("text/html;charset=utf-8");
 ServletOutputStream sos = resp.getOutputStream();//获取字节输出流
 sos.write("头发没了哦".getBytes("utf-8"));//输出纯文本数据

注意不能同时使用PrintWriter和OutputStream,比如如下代码会报错

OutputStream os = response.getOutputStream();
os.write("monkey".getBytes());
PrintWriter out = response.getWriter();
out.println("cat");

中文乱码问题解决

/*方式一
resp.setCharacterEncoding("utf-8");//获取流对象之前,设置流的默认编码:ISO-8859-1 设置为其他的编码格式
resp.setHeader("content-type","text/html;charset=utf-8"); //告知浏览器服务器发送消息体数据的编码,建议浏览器使用该编码解码
PrintWriter pw = resp.getWriter();//获取字符输出流
pw.write("

monkey

"); pw.write("头发没了哦"); */ //方式二 resp.setContentType("text/html;charset=utf-8");


重定向

是一种资源跳转方式

Servlet请求与响应、ServletContext对象_第3张图片
实现重定向

方法一:设置状态码+设置路径

@WebServlet("/resDemo1")
public class ResponseDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("demo1执行了哦");
        resp.setStatus(302); //设置状态码
        resp.setHeader("location","/resDemo2"); //设置路径
    }
}

@WebServlet("/resDemo2")
public class ResponseDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("访问demo1,自动跳转到这里的demo2");
    }
}

方法二:使用直接的方法设置路径

resp.sendRedirect("/resDemo2");

重定向的特点 - - redirect

  • 地址栏发生变化
  • 重定向可以访问其他站点的资源,如百度、csdn等
  • 重定向是两次请求,不能使用request对象共享数据

ServletContext

基本概述

ServletContext原理

  • ServletContext是在服务器,被所有客户端共享
  • ServletContext是当web应用启动时,自动创建
  • 当Web应用关闭/tomcat应用关闭/对Web应用reload时,都会造成ServletContext销毁

ServletContext接口代表整个web应用,是Servlet中最大的接口,呈现了Web应用的Servlet视图,获得方法

ServletContext context1 = request.getServletContext();
ServletContext context2 = this.getServletContext();
ServletContext功能

1.获取MIME类型:在互联网通信过程中定义的一种文件数据类型,如text/html、image/jpeg
String getMimeType(String file) - - 获取MIME类型

2.多个Servlet之间共享数据(域对象)
setAttribute(String name,Object object) - - 向ServletContext中存数据
getAttribute(String name) - - 从ServletContext中获取数据
removeAttribute(String name) - - 从ServletContext中移除数据

/*两类之间共享context变量*/

@WebServlet("/resDemo1")
public class ResponseDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        context.setAttribute("v","monkey");
    }
}

@WebServlet("/resDemo2")
public class ResponseDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        Object obj = context.getAttribute("v");
        System.out.println(obj);
    }
}

3.获取当前WEB项目中指定的资源文件
getRealPath(String str) - - 获取资源绝对路径

//获取ServletContext对象
ServletContext context = this.getServletContext();
/* 
'/'代表E:\JavaWeb\out\artifacts\JavaWeb_war_exploded下的文件
如果想要访问WEB-INF下的文件,则路径写'/WEB-INF/other.html'
若要访问src下的文件,则路径写'/WEB-INF/classes/other.txt'
 */
//读取web项目文件下的文件
String realPath = context.getRealPath("/monkey.txt");
System.out.println(realPath);//E:\JavaWeb\out\artifacts\JavaWeb_war_exploded\monkey.txt
//读取该文件的内容
BufferedReader br = new BufferedReader(new FileReader(realPath));
String MyContext = br.readLine();
System.out.println(MyContext);

你可能感兴趣的:(Java,Web)