文章目录

  • Servlet ②
  • 1. HttpServletRequest类
  • 2. 请求转发
  • 2. base标签
  • 3. HttpServletResponse类
  • 4. 请求重定向


Servlet ②

1. HttpServletRequest类

每次只要有请求进入Tomcat服务器就会把请求过来的HTTP协议解析好,封装到HttpServletRequest对象中,然后传递service()方法中(doGet()或者doPost()),给我们使用。我们根据这个对象获得所有请求的信息

常用方法(看注释⭐):

// 该Servlet程序访问路径是 /hello02
public class HelloServlet02 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestURI(); 			  // 获取请求的资源路径
        req.getRequestURL();		 	  // 获取请求的统一资源定位法 - 绝对路径
        req.getRemoteHost();			  // 获取客户端的ip地址
        req.getHeader("User-Agent"); 	  // 获取请求头
        req.getMethod();				  // 获取请求的方式
        req.setAttribute("key", "value"); // 设置request域数据
        req.getAttribute("key"); 		  // 获得request域数据

        req.getParameter("username"); //获取请求的参数,注意在Post请求中,有中文可能出现乱码,需要设置字符集
        //req.setCharacterEncoding("UTF-8"); 
        //设置请求体的字符集为UTF-8,一定要在获取请求前调用,
        //(获取-设置-获取)这样两个都不行都可能乱码,必须(设置-获取-获取),这样的顺序
        
        req.getParameter("password");    //获取请求的参数
        req.getParameterValues("hobby"); //获取请求的(多个值),返回String[]
        req.getRequestDispatcher("/hello01"); //获取请求转发对象,即RequestDispatcher类型
    }
}

前端:

<body>
<form action="http://localhost:8080/dynamicobject/hello02" method="get">
    用户名:<input type="text" name="username"> <br/>
    密码:<input type="password" name="password"> <br/>
    爱好:<input type="checkbox" name="hobby" value="CPP"> C++
    <input type="checkbox" name="hobby" value="Java"> Java
    <input type="checkbox" name="hobby" value="JavaScript"> JavaScript
    <input type="submit"/>
</form>
</body>



2. 请求转发

请求转发:是指服务器收到请求后,从一个资源跳转到另一个资源的操作,Servlet01程序 -> Servlet02程序

例如:Servlet01Servlet02程序共同完成一个业务。Servlet01程序获取客户端发来的数据并处理,把 Servlet02程序需要的数据通过setAttribute()方法(域对象),存储在request域公共区域。

然后请求转发 :

// 注意参数写法,必须以斜杠开头,后面是资源路径。
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet02");  //获取请求转发对象
requestDispatcher.forward(req, resp); //前往 Servlet02程序,记得传入参数!!

然后在Servlet02程序中getAttribute(),根据key获得数据,处理业务。



特点: ⭐⭐

  • 浏览器地址没有变化!
  • 它们是一次请求!
  • 他们共享Request域中的数据 (因为forward方法中把req和resp都传进去了)
    Servlet01:req.setAttribute("key", "value")Servlet02:req.getAttribute("key")
  • 可以转发到 WEB-INF 目录下 (用浏览器输入直接访问不到)
    例如:req.getRequestDispatcher("/WEB-INF/test.html")
  • 不能访问当前工程以外的资源
    例如:req.getRequestDispatcher("www.baidu.com")

2. base标签

base可以设置当前页面中所有标签工作时,参考base的src属性路径进行跳转,会忽略掉当前浏览器地址栏的地址,去参考base的src属性值。

web/a/b/c.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>c</title>
    <base href="http://localhost:8080/dynamicobject/a/b/c.html"/> 
    <base href="http://localhost:8080/dynamicobject/a/b/"/> 
    <!-- 最后的资源名可以省略,因为.../只看目录,注意斜杠不能省略,因为带个斜杠才能说明我是个目录--> 
    <!-- 设置参考路径和不用转发一样的,就能正常了-->
</head>
<body>
    <div>这是web目录下a目录下b目录下的c.html文件</div> <br/>
    <a href="../../index.html">跳回首页</a> <br/>
    <!-- 如果用请求转发这样就跳不回去了,因为相对路径在工作时会参考当前浏览器地址栏中的地址来进行跳转
         如果没用请求转发是这样的:http://localhost:8080/dynamicobject/a/b/c.html/../../index.html,
		 一个../去掉一个后面的目录,结果没问题
         如果用请求转发是这样的:http://localhost:8080/dynamicobject/forwardC/../../index.html,这样当然就会404
         所以base标签出现了,base可以设置当前页面中所有标签工作时,参考那个路径进行跳转-->
</body>
</html>

⭐⭐

web中 / 斜杠的不同意义:(/是一种绝对路径)

  • / 被浏览器解析得到地址是:http://ip:port/例如:<a href="/">斜杠</a>
  • / 被服务器解析得到:http://ip:port/工程路径例如:<url-pattern>/hello</url-pattern>context.getRealPath("/") 工程部署的绝对路径
    req.getRequestDispatcher("/hello01"); 获取请求转发对象
  • 特殊情况:response.sendRedirect("/"); 重定向
    虽然写在服务器上但不是直接解析,而是发给浏览器解析,会得到http://ip:port/


3. HttpServletResponse类

1.和HttpServletRequest类一样,每次请求进来,tomcat服务器都会创建一个Response对象,传递给Servlet程序去使用。

HttpServletRequest:表示请求过来的信息

HttpServletResponse :表示所有响应的信息,可以设置返回给客户端的信息

2.两个响应流

两个响应输出流

作用

字符流

getOutputStream()

常用于下载(传递二进制数据)

字节流

getWriter()

常用于回传字符串(常用)

两个流只能同时只有一个,否则报错。

⭐使用:

往客户端回传字符串?显示在页面

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
    //response.getOutputStream();

    System.out.println(response.getCharacterEncoding()); // 服务器默认是ISO-8859-1
    response.setCharacterEncoding("UTF-8");// 设置服务器的字符集,但浏览器的字符集可能表示UTF-8,浏览器默认是GBK
    response.setHeader("Content-Type", "text/html;charset=UTF-8"); // 通过响应头设置浏览器也使用UTF-8!
   
    PrintWriter writer = response.getWriter();
    writer.write("响应的字符串"); // 中文可能出现乱码
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
    //response.getOutputStream();
    
    // 一行更简单,同时设置服务器和客户端浏览器的编码,还设置了响应头,一定要做获取流对象之前调用才有效!!
    response.setContentType("text/html; charset=UTF-8");  // !!
    PrintWriter writer = response.getWriter();
    writer.write("响应的字符串"); // 中文可能出现乱码
}



4. 请求重定向

请求重定向是指:客户端给服务器发请求,然后服务器告诉客户端,我给你新地址,你去新地址访问,叫请求重定向。(可能之间的地址已经被废弃了)

  1. 告诉他我已经搬迁了,响应码:302
  2. 搬迁的地址,响应头:Location
  3. 重定向后浏览器会重新去新地址发起请求,收到最终的返回,解析展示在页面上
public class Response01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
        System.out.println("Response01");

        // 第一种:1.设置状态码
        resp.setStatus(302);
        // 2.设置响应头
        resp.setHeader("Location", "http://localhost:8080/dynamicobject/response02"); //请求重定向
        
        //第二种: 由于302和Location都是固定的,一行代替上面的两行!!!!
        resp.sendRedirect("http://localhost:8080/dynamicobject/response02");
    }
}

// 细节:浏览器地址栏变了response01 -> response02,http://localhost:8080/dynamicobject/response02
// 浏览器内按F12可以看到,有两个请求,第一个状态码s302
public class Response02 extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException {
        System.out.println("Response02");

        resp.getWriter().write("Response02 is a result"); 
    }
}

特点: ⭐⭐

  • 浏览器地址有变化 (请求转发是没有变化的)
  • 它是两次请求
  • 不共享Resqust域中的数据(因为Tomcat每次请求都会重新封装为一个新的HttpServletRequest类)
  • 不能访问到WEB-INF下的资源 (因为重定向还是浏览器请求)
  • 能访问工程以外的地址
    例如:resp.setHeader("Location", "http://www.baidu.com");