JavaWeb学习(三)-Servlet体系结构(HTTPServlet抽象类、HttpServletRequest和HttpServletResponse接口、request和response对象)

Servlet体系结构

在这里插入图片描述

package cn.zhukun.web.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/demo")
public class ServletDemo implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.printf("servlet体系结构");
    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {
    }
}

前面我们编写Servlet是通过实现Servlet接口来编写的,但是,使用这种方法,则必须要实现Servlet接口中定义的所有的方法,但是其中我们主要使用的还是service方法,剩余的四种方法中没有任何东西也要去实现,并且还需要自己手动的维护ServletConfig这个对象的引用。因此,这样去实现Servlet是比较麻烦的。

1、GenericServlet抽象类

GenericServlet抽象类的出现很好的解决了这个问题。本着尽可能使代码简洁的原则,GenericServlet实现了Servlet和ServletConfig接口,下面是GenericServlet抽象类的具体代码:

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
    private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
    private transient ServletConfig config;
 
    public GenericServlet() {
    }
 
    public void destroy() {
    }
 
    public String getInitParameter(String name) {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameter(name);
        }
    }
 
    public Enumeration<String> getInitParameterNames() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameterNames();
        }
    }
 
    public ServletConfig getServletConfig() {
        return this.config;
    }
 
    public ServletContext getServletContext() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletContext();
        }
    }
 
    public String getServletInfo() {
        return "";
    }
 
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
 
    public void init() throws ServletException {
    }
 
    public void log(String msg) {
        this.getServletContext().log(this.getServletName() + ": " + msg);
    }
 
    public void log(String message, Throwable t) {
        this.getServletContext().log(this.getServletName() + ": " + message, t);
    }
 
    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
 
    public String getServletName() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletName();
        }
    }
}

GenericServlet抽象类相比于直接实现Servlet接口,有以下几个好处:
1.为Servlet接口中的所有方法提供了默认的实现,则程序员需要什么就直接改什么,不再需要把所有的方法都自己实现了。
2.提供方法,包围ServletConfig对象中的方法。
3.将init( )方法中的ServletConfig参数赋给了一个内部的ServletConfig引用从而来保存ServletConfig对象,不需要程序员自己去维护ServletConfig了。

2、HttpServlet抽象类

虽然GenricServlet是对Servlet一个很好的加强,但是也不经常用,因为他不像HttpServlet那么高级。HttpServlet才是主角,在现实的应用程序中被广泛使用。
之所以所HttpServlet要比GenericServlet强大,其实也是有道理的。HttpServlet是由GenericServlet抽象类扩展而来的,HttpServlet抽象类的声明如下所示:

public abstract class HttpServlet extends GenericServlet implements Serializable 

HttpServlet抽象类是继承于GenericServlet抽象类而来的。

HttpServlet的service方法的:

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    HttpServletRequest request;
    HttpServletResponse response;
    try {
        request = (HttpServletRequest)req;
        response = (HttpServletResponse)res;
    } catch (ClassCastException var6) {
        throw new ServletException("non-HTTP request or response");
    }
 
    this.service(request, response);
}

HttpServlet中的service方法把接收到的ServletRequsest类型的对象转换成了HttpServletRequest类型的对象,把ServletResponse类型的对象转换成了HttpServletResponse类型的对象。之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个HttpServletRequest对象和HttpServletResponse对象,预备使用HTTP。因此,转换类型当然不会出错了。转换之后,service方法把两个转换后的对象传入了另一个service方法,那么我们再来看看这个方法是如何实现的:

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    long lastModified;
    if (method.equals("GET")) {
        lastModified = this.getLastModified(req);
        if (lastModified == -1L) {
            this.doGet(req, resp);
        } else {
            long ifModifiedSince = req.getDateHeader("If-Modified-Since");
            if (ifModifiedSince < lastModified) {
                this.maybeSetLastModified(resp, lastModified);
                this.doGet(req, resp);
            } else {
                resp.setStatus(304);
            }
        }
    } else if (method.equals("HEAD")) {
        lastModified = this.getLastModified(req);
        this.maybeSetLastModified(resp, lastModified);
        this.doHead(req, resp);
    } else if (method.equals("POST")) {
        this.doPost(req, resp);
    } else if (method.equals("PUT")) {
        this.doPut(req, resp);
    } else if (method.equals("DELETE")) {
        this.doDelete(req, resp);
    } else if (method.equals("OPTIONS")) {
        this.doOptions(req, resp);
    } else if (method.equals("TRACE")) {
        this.doTrace(req, resp);
    } else {
        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[]{method};
        errMsg = MessageFormat.format(errMsg, errArgs);
        resp.sendError(501, errMsg);
    }
}

这个service方法的参数是HttpServletRequest对象HttpServletResponse对象,刚好接收了上一个service方法传过来的两个对象。
接下来我们再看看service方法是如何工作的,我们会发现在service方法中还是没有任何的服务逻辑,但是却在解析HttpServletRequest中的方法参数,并调用以下方法之一:doGet,doPost,doHead,doPut,doTrace,doOptions和doDelete

这7种方法中,每一种方法都表示一个Http方法。doGet和doPost是最常用的。所以,如果我们需要实现具体的服务逻辑,不再需要覆盖service方法了,只需要覆盖doGet或者doPost就好了。

总之,HttpServlet有两个特性是GenericServlet所不具备的:

  • 不用覆盖service方法,而是覆盖doGet或者doPost方法。(在少数情况,还会覆盖其他的5个方法。)
  • 使用的是HttpServletRequest和HttpServletResponse对象。

开发中写Servlet最常用的就是继承HttpServlet抽象类,复写doGet或doPost方法

ServletRequset接口和它的子接口HttpServletRequest接口

1、Request和Response原理:

在这里插入图片描述

  • request和response对象是由服务器创建的,我们来使用它们
  • request对象是来获取请求消息,response对象用来设置响应消息

request对象继承体系结构:
在这里插入图片描述

2、ServletRequset接口

Servlet容器对于接受到的每一个Http请求,都会创建一个ServletRequest对象,并把这个对象传递给Servlet的Sevice( )方法。其中,ServletRequest对象内封装了关于这个请求的许多详细信息。

public interface ServletRequest {
    int getContentLength();//返回请求主体的字节数
 
    String getContentType();//返回主体的MIME类型
 
    String getParameter(String var1);//返回请求参数的值 ,ServletRequest中最常用的方法,可用于获取查询字符串的值
}

3、HttpServletRequest接口

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法我们可以分别获得HTTP请求的请求行,请求头和请求体
在这里插入图片描述

3.1获得客户机请求行信息:

String getMethod():获取请求方式
String getContextPath():获取虚拟目录
String getServletPath():获取Servlet路径
getRequestURL():返回客户端发出请求时的完整URL。
String getProtocol():获取协议及版本
getRequestURI(): 返回请求行中的资源名部分。
getQueryString ():返回请求行中的参数部分。
getPathInfo():方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
getRemoteAddr():方法返回发出请求的客户机的IP地址。
getRemoteHost():方法返回发出请求的客户机的完整主机名。
getRemotePort():方法返回客户机所使用的网络端口号。
getLocalAddr():方法返回WEB服务器的IP地址。
getLocalName():方法返回WEB服务器的主机名。
案例:

package cn.zhukun.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /**
         * 1.获得客户机信息
         */
        String requestUrl = request.getRequestURL().toString();//得到请求的URL地址
        String requestUri = request.getRequestURI();//得到请求的资源
        String queryString = request.getQueryString();//得到请求的URL地址中附带的参数
        String remoteAddr = request.getRemoteAddr();//得到来访者的IP地址
        String remoteHost = request.getRemoteHost();
        int remotePort = request.getRemotePort();
        String remoteUser = request.getRemoteUser();
        String method = request.getMethod();//得到请求URL地址时使用的方法
        String pathInfo = request.getPathInfo();
        String localAddr = request.getLocalAddr();//获取WEB服务器的IP地址
        String localName = request.getLocalName();//获取WEB服务器的主机名
        response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
        //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
        response.setHeader("content-type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write("获取到的客户机信息如下:");
        out.write("<hr/>");
        out.write("请求的URL地址:"+requestUrl);
        out.write("<br/>");
        out.write("请求的资源:"+requestUri);
        out.write("<br/>");
        out.write("请求的URL地址中附带的参数:"+queryString);
        out.write("<br/>");
        out.write("来访者的IP地址:"+remoteAddr);
        out.write("<br/>");
        out.write("来访者的主机名:"+remoteHost);
        out.write("<br/>");
        out.write("使用的端口号:"+remotePort);
        out.write("<br/>");
        out.write("remoteUser:"+remoteUser);
        out.write("<br/>");
        out.write("请求使用的方法:"+method);
        out.write("<br/>");
        out.write("pathInfo:"+pathInfo);
        out.write("<br/>");
        out.write("localAddr:"+localAddr);
        out.write("<br/>");
        out.write("localName:"+localName);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

在这里插入图片描述

3.2获得客户机请求头信息:

getHeader(string name):String
  getHeaders(String name):Enumeration
  getHeaderNames()

package cn.zhukun.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
        //通过设置响应头控制浏览器以UTF-8的编码显示数据
        response.setHeader("content-type", "text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        Enumeration<String> reqHeadInfos = request.getHeaderNames();//获取所有的请求头
        out.write("获取到的客户端所有的请求头信息如下:");
        out.write("<hr/>");
        while (reqHeadInfos.hasMoreElements()) {
            String headName = (String) reqHeadInfos.nextElement();
            String headValue = request.getHeader(headName);//根据请求头的名字获取对应的请求头的值
            out.write(headName+":"+headValue);
            out.write("<br/>");
        }
        out.write("<br/>");
        out.write("获取到的客户端Accept-Encoding请求头的值:");
        out.write("<hr/>");
        String value = request.getHeader("Accept-Encoding");//获取Accept-Encoding请求头对应的值
        out.write(value);
        Enumeration<String> e = request.getHeaders("Accept-Encoding");
        while (e.hasMoreElements()) {
            String string = (String) e.nextElement();
            System.out.println(string);
        }
    }   
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

在这里插入图片描述

3.3 获取请求体数据:

请求体:只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数。request对象将请求体的数据封装成流

  1. 获取流对象
    BufferedReader getReader():获取字符输入流,只能操作字符数据
    ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
  2. 再从流对象中拿数据

案例:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="demo4" method="post">
      用户名(文本框)<input type="text" name="username" value="请输入用户名"><br>&nbsp;&nbsp;(密码框)<input type="password" name="userpass" value="请输入密码"><br>
      <input type="submit" value="提交(提交按钮)">
    </form>
  </body>
</html>
package cn.zhukun.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求消息体--请求参数
        //1、获取字符流
        BufferedReader br = request.getReader();
        String line = null;
        while ((line=br.readLine())!=null)
        {
            System.out.println(line);
        }
    }
}

在这里插入图片描述
在这里插入图片描述

3.4获得客户机请求参数(客户端提交的数据):

getParameter(String):根据参数名称获取参数值 ——常用
getParameterValues(String name):根据参数名称获取参数值的数组 ——常用
getParameterNames():获取所有请求的参数名称——不常用
getParameterMap():获取所有参数的map集合——编写框架时常用

案例:
get方式

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="demo3" method="get">
      用户名(文本框)<input type="text" name="username" value="请输入用户名"><br>&nbsp;&nbsp;(密码框)<input type="password" name="userpass" value="请输入密码"><br>
      <input type="submit" value="提交(提交按钮)">
    </form>
  </body>
</html>
package cn.zhukun.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");//获取填写的用户名
        String userpass = request.getParameter("userpass");//获取填写的密码
        response.setContentType("text/html;charset=UTF-8");//设置客户端浏览器以UTF-8编码解析数据
        PrintWriter out = response.getWriter();
        out.write("用户名:"+username);
        out.write("<br>");
        out.write("密码:"+userpass);

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

在这里插入图片描述
在这里插入图片描述
post方式:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="demo3" method="post">
      用户名(文本框)<input type="text" name="username" value="请输入用户名"><br>&nbsp;&nbsp;(密码框)<input type="password" name="userpass" value="请输入密码"><br>
      <input type="submit" value="提交(提交按钮)">
    </form>
  </body>
</html>
package cn.zhukun.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String username = request.getParameter("username");//获取填写的用户名
        String userpass = request.getParameter("userpass");//获取填写的密码
        response.setContentType("text/html;charset=UTF-8");//设置客户端浏览器以UTF-8编码解析数据
        PrintWriter out = response.getWriter();
        out.write("用户名:"+username);
        out.write("<br>");
        out.write("密码:"+userpass);

    }
}

在这里插入图片描述
在这里插入图片描述

解决post提交方式的乱码:

request.setCharacterEncoding("UTF-8");

解决get提交的方式的乱码:tomcat 8 已经将get方式乱码问题解决了

parameter = newString(parameter.getbytes("iso8859-1"),"utf-8");

3.5请求跳转

请求转发:一种在服务器内部的资源跳转方式
步骤:

  1. 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
  2. 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)

案例:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <form action="demo4" method="post">
      用户名(文本框)<input type="text" name="username" value="请输入用户名"><br>&nbsp;&nbsp;(密码框)<input type="password" name="userpass" value="请输入密码"><br>
      爱好:<input type="checkbox" name="hobby" value="game">游戏
      <input type="checkbox" name="hobby" value="study">学习
      <input type="checkbox" name="hobby" value="running">跑步
      <input type="submit" value="提交(提交按钮)">
    </form>
  </body>
</html>
package cn.zhukun.web.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo4被访问了");
        response.setHeader("Content-Type","text/html;charset=UTF-8");
        response.setContentType("text/html;charset=UTF-8");//设置客户端浏览器以UTF-8编码解析数据
        PrintWriter out = response.getWriter();

        //转发资源到demo3
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/demo3");
        requestDispatcher.forward(request,response);
    }
}
package cn.zhukun.web.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo3被访问了");
        request.setCharacterEncoding("UTF-8");
        String username = request.getParameter("username");//获取填写的用户名
        String userpass = request.getParameter("userpass");//获取填写的密码
        //设置HttpServletResponse使用utf-8编码
        response.setCharacterEncoding("utf-8");
        //通知浏览器使用utf-8编码
        response.setHeader("Content-Type","text/html;charset=UTF-8");
        response.setContentType("text/html;charset=UTF-8");//设置客户端浏览器以UTF-8编码解析数据
        PrintWriter out = response.getWriter();
        out.write("用户名:"+username);
        out.write("<br>");
        out.write("密码:"+userpass);
        out.write("<br>");
        out.write("爱好:");

        String[] hobbies = request.getParameterValues("hobby");
        for (String hobby: hobbies)
        {
            out.write(hobby);
            out.write("&nbsp&nbsp");
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
表单提交到demo4,demo4被访问了,demo4将资源跳转到demo3,将request对象和response对象转发给demo3,demo3被访问,但浏览器地址栏路径还是demo4。
特点:

  1. 浏览器地址栏路径不发生变化
  2. 只能转发到当前服务器内部资源中。
  3. 转发是一次请求

3.6共享数据

域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:

  1. void setAttribute(String name,Object obj):存储数据
  2. Object getAttitude(String name):通过键获取值
  3. void removeAttribute(String name):通过键移除键值对
package cn.zhukun.web.servlet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/demo4")
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo4被访问了");
        //存储数据到request域中
        request.setAttribute("msg","hello");
        //转发资源到demo3
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/demo2");
        requestDispatcher.forward(request,response);
    }
}
package cn.zhukun.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo2被访问了");
        //获取数据
        Object msg = request.getAttribute("msg");
        System.out.println(msg);
    }
}

在这里插入图片描述
在这里插入图片描述
demo4中在request域中保存的数据“hello”在资源跳转到demo3后被共享到了demo3

ServletResponse接口和它的子接口HttpServletResponse接口

1、ServletResponse接口

javax.servlet.ServletResponse接口表示一个Servlet响应,在调用Servlet的Service( )方法前,Servlet容器会先创建一个ServletResponse对象,并把它作为第二个参数传给Service( )方法。ServletResponse隐藏了向浏览器发送响应的复杂过程。

public interface ServletResponse {
    String getCharacterEncoding(); 
    String getContentType();
    ServletOutputStream getOutputStream() throws IOException; 
    PrintWriter getWriter() throws IOException; 
    void setCharacterEncoding(String var1); 
    void setContentLength(int var1); 
    void setContentType(String var1); 
    void setBufferSize(int var1);
    int getBufferSize();
    void flushBuffer() throws IOException;
    void resetBuffer();
    boolean isCommitted();
    void reset();
    void setLocale(Locale var1);
    Locale getLocale();
}

其中的getWriter方法,它返回了一个可以向客户端发送文本的的Java.io.PrintWriter对象。默认情况下,PrintWriter对象使用ISO-8859-1编码(该编码在输入中文时会发生乱码)。
在向客户端发送响应时,大多数都是使用该对象向客户端发送HTML。还有一个方法也可以用来向浏览器发送数据,它就是getOutputStream,从名字就可以看出这是一个二进制流对象,因此这个方法是用来发送二进制数据的。
在发送任何HTML之前,应该先调用setContentType()方法,设置响应的内容类型,并将“text/html”作为一个参数传入,这是在告诉浏览器响应的内容类型为HTML,需要以HTML的方法解释响应内容而不是普通的文本,或者也可以加上“charset=UTF-8”改变响应的编码方式以防止发生中文乱码现象。

2、HttpServletResponse接口

HttpServletResponse接口,它继承自ServletResponse接口,专门用来封装HTTP响应消息。 由于HTTP请求消息分为状态行,响应消息头,响应消息体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码,响应消息头,响应消息体的方法

HttpServletResponse内封装的响应

在这里插入图片描述
通过Response设置响应
void addCookie(Cookie var1);//给这个响应添加一个cookie
void addHeader(String var1, String var2);//给这个请求添加一个响应头
void sendRedirect(String var1) throws IOException;//发送一条响应码,讲浏览器跳转到指定的位置
void setStatus(int var1);//设置响应行的状态码

PrintWriter getWriter()
获得字符流,通过字符流的write(String s)方法可以将字符串设置到response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。
ServletOutputStream getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,再由Tomcat服务器将字节内容组成Http响应返回给浏览器。

Response的乱码问题
原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,所以需要更改response的编码方式

两种方法:
第一种:

//设置HttpServletResponse使用utf-8编码
response.setCharacterEncoding("utf-8");
//通知浏览器使用utf-8编码
response.setHeader("Content-Type","text/html;charset=UTF-8");

第二种:

//包含第一种方式的两种功能
response.setContentType("text/html;charset=UTF-8");
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值