Servlet学习Chapter2

HttpServletResponse

常见的用法主要有:

  • 发送响应码
    1. sendError(int num):发送错误码num,其中错误码是4和5类状态码
    2. sendError(int num,String msg):发送错误码,提示信息为msg.
    3. setStatus(int num):发送状态码num,其中这些状态码是1,2,3类状态码
  • 设置响应头
    1. setHeader(header,value):设置响应头,它的值为value,这是单值的,即这个响应头只有单个值。(这是最常用的).例如我们设置Location来实现重定向.
 public class AServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
         /*//发送重定向之后,同时需要设置对应的响应头Location,其中对应的值就是我们需要
         //重定向的URL
         resp.setStatus(302);//发送状态码,表示重定向
         resp.setHeader("Location","/response/BServlet");*/
         //可以调用sendRedirect()来代替上面的2行代码,从而实现它的重定向
         System.out.println("this is AServlet!!!!");
         resp.sendRedirect("/response/BServlet");
 
     }
 }
 
 
 public class BServlet extends HttpServlet {
     @Override
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         /*
         设置响应编码,如果不设置的话,那么下面发送的数据就会出现乱码。因为
         服务端默认是iso编码,而客户端是gbk,所以我们需要调用setCharacterEncoding来
         设置可以识别中文的编码,例如utf-8或者gbk,但是设置utf-8同样出现乱码,因为
         此时服务端和客户端的编码依旧是不一样的。所以还需要通知客户端,服务端使用的编码
         因此可以利用setHeader("Content-Type","text/html;charset=utf-8")来,通过设置
         Content-Type响应头,一方面执行了setCharacterEncoding("utf-8")来设置服务端的编码,
         同时会告诉客户端,服务端所使用的编码,这样客户端就会自动使用对应的编码了.
         而setHeader("Content-Type","text/html;charset=utf-8")的快捷方式为
         setContentType("text/html;charset=utf-8");
         */
         response.setContentType("text/html;charset=utf-8");
         System.out.println("这是我们重定向的BServlet!!!!");
         response.getWriter().println("这是我们重定向的BServlet!!!");
     }
 }

这时候我们一旦在浏览器地址栏上面输入localhost:8080/response/AServlet,回车之后,就会发现地址栏变成了localhost:8080/response/BServlet,并且输出了在BServlet类中发送的实体数据 。测试结果如下:
在这里插入图片描述
同时我们可以设置Refresh响应头,这个响应头相当于定向重定向的,可以设置多少秒之后就会重定向到新的Servlet中.例如下面的代码:

public class CServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		/*设置给AServlet发送请求的时候,AServlet的响应编码*/
		response.setContentType("text/html;charset=utf-8");
		response.getWriter().println("这是AServlet!");
		response.setHeader("Refresh","5;/request/BServlet");
	}
}

测试结果位:
在这里插入图片描述

  1. addHeader(header,value):设置响应头,它的值不只是value,它是一个多值的,即这个响应头有多个值
  2. setIntHeader(header,value):设置int类型的响应头,它的值为value,它是单值的,即一个响应头只有一个值。
  3. addIntHeader(header,value):设置int类型的响应头,它的值不只是value,它是多值的。
  4. setDateHeader(header,value):设置毫秒类型(即long类型的)的响应头,同样这是一个单值的。
  5. addDateHeader(header,value):设置毫秒类型的多值的响应头
    ⭐通过上面,我们可以知道,只要是set开头的,那么响应头就是单值的,因为我们新的值就会覆盖掉原来的值,但是add开头的,那么响应头就是多值的,给这个响应头再添加值。
  • 获取对应的流,通过流来发送实体数据

    1. getWriter():获取字符流PrintWriter,然后可以调用println(msg)来发送实体数据
    2. getOutputStream():获取字节流,然后调用write方法来发送实体数据.
    3. 值得注意的是,不可以同时出现getWriter和getOutputStream,否则就会发送异常IllegalStateException
     public class EServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                response.setContentType("text/html;charset=utf-8");//设置响应编码为utf-8,同时告诉给客户端,服务端的编码
                response.getWriter().println("这是使用getWriter发送的数据!");
                response.getOutputStream().write("这是使用getOutputStream发送实体数据".getBytes());
            }
     }
    

    测试结果为:
    在这里插入图片描述

HttpServletRequest

常见的用法有:

  • getMethod():来获取对应的请求方法

  • getRemoteAddr():来获取客户端的ip地址

  • getHeader():获取请求头的数据,例如通过获取User-Agent请求头,我们就可以获取客户端的操作系统,以及浏览器等信息.

  • 获取地址栏URL中的相关数据

    • getScheme():获取所使用的协议
    • getServerName():获取服务器的名字
    • getServerPort():获取服务点所使用的端口
    • getContextPath():获取项目路径
    • getServletPath():获取Servlet的路径
    • getQueryString():获取请求参数,URL中?后面的一些列字符串
    • getRequestURI():即项目路径 + Servlet路径
    • getRequestURL():即URL中?前面的一系列字符串
     public class AServlet extends HttpServlet {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                //1、调用getMethod来获取请求方法
                PrintWriter writer = resp.getWriter();
                String method = req.getMethod();
                writer.println("getMethod() = " + method);
                //2、调用getRemoteAddr()来获取远程客户主机的ip地址
                String remoteAddr = req.getRemoteAddr();
                writer.println("getRemoteAddr() = " + remoteAddr);
                //3、获取URL上的相关信息
                String scheme = req.getScheme();//调用getScheme来获取协议
                writer.println("getScheme() = " + scheme);
                //调用getServerName()来获取服务器的名字
                String serverName = req.getServerName();
                writer.println("getServerName() = " + serverName);
                //调用getServerPort()来获取服务器的端口号
                writer.println("getServerPort() = " + req.getServerPort());
                //调用getContextPath来获取项目名
                writer.println("getContextPath() = " + req.getContextPath());
                //调用getServletPath来获取Servlet名字
                writer.println("getServletPath = " + req.getServletPath());
                //调用getQueryString来获取参数,注意的是,如果参数的值是个中文,那么这时候会发生乱码
                String queryString = req.getQueryString();
                writer.println("getQueryString() = " + queryString);
                //调用getRequestURI来获取URI(即web.xml中的url)
                writer.println("getRequestURI() = " + req.getRequestURI());
                //调用getRequestURL来获取URL,即浏览器上面的URL中?前面一系列字符串
                writer.println("getRequestURL() = " + req.getRequestURL());
            }
     }
    

    测试结果:
    在这里插入图片描述

  • 获取请求参数对应的值

    • String getParameter(target):获取请求参数target的值
    • String[ ] getParameterValues(target):获取请求参数target的所有值。这是针对的是多值的参数,例如复选框
    • Enumeration getParameters():获取所有请求参数的名字
    • Map<String,String[ ]> getParameterMap():获取所有的请求参数以及对应的值。
 public class DServlet extends HttpServlet {
         @Override
         protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
             /*
             通过超链接来获取请求参数,也即是GET请求
             此时超链接所在的页面是一个UTF-8的,那么这时候发送请求的参数中含有中文
             那么request调用响应的方法来获取这个参数的值,由于服务器的编码是iso的,那么
             必然会发生了乱码。所以需要在获取值之后,用iso进行回编,然后在用utf-8进行重编
              */
             String value = req.getParameter("xxx");//调用getParameter(target)表示获取参数target的值
             //服务器的默认编码为iso,那么我们需要先将iso的编码形式回退,然后在重编
             byte[] bytes = value.getBytes("iso-8859-1");
             //重建对应的编码形式
             String value1 = new String(bytes,"utf-8");
             System.out.println("xxx的value为:" + value1);
             String yyy = req.getParameter("yyy");
             //回退,然后在重编
             byte[] bytes1 = yyy.getBytes("iso-8859-1");
             String yyy1 = new String(bytes1, "utf-8");
             System.out.println("yyy的value为: " + yyy1);
         }
     
         @Override
         protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
             /*
             使用Post请求的时候,直接利用req调用对应方法来获取参数的值,那么出现乱码的时候,
             所以在调用getParameter等方法之前,执行req.setCharacterEncoding设置编码
             */
             req.setCharacterEncoding("utf-8");//需要用req来设置对应的编码
             Enumeration<String> parameterNames = req.getParameterNames();
             while(parameterNames.hasMoreElements()){
                 String parameter = parameterNames.nextElement();
                 //调用getParameter(name)来获取name参数的值
                 System.out.println(parameter + ": " + Arrays.toString(req.getParameterValues(parameter)));
             }
             //调用方法getParameterMap()来获取所有的参数,并且返回的值是一个String[],因为
             //这些参数中有可能含有多个值,例如下面的hobby就是多值的
             Map<String, String[]> parameterMap = req.getParameterMap();
             for(Map.Entry<String,String[]> entry: parameterMap.entrySet()){
                 String name = entry.getKey();
                 String[] value = entry.getValue();
                 System.out.println(name + ": " + Arrays.toString(value));
             }
     
     
         }
 }

对应的html页面:

 <!DOCTYPE html>
 <html lang="en">
     <head>
         <meta charset="UTF-8"><!--设置了解码的形式为UTF-8-->
         <title>login.html</title>
     </head>
     <body>
         <a href="/request/DServlet?xxx=张三&yyy=李四">通过链接来提交表单</a><br>
         <form action="/request/DServlet" 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="乒乓球">乒乓<br>
             <input type="submit" value="登录">
         </form>
     </body>
 </html>

所以一开始,直接在地址栏上输入:localhost:8080/login.html来到我们上面html代码页面,然后点击表单提交,或者超链接体,测试结果为:
在这里插入图片描述

  • 请求转发和请求包括
    首先request对象调用getRequestDispatcher(“新的Servlet”),获取RequestDispatcher对象dispatcher
    然后dispatcher调用forward进行请求转发,调用include进行请求包括。
    请求转发:
   public class EServlet extends HttpServlet {
           @Override
           protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               //设置响应编码
               response.setContentType("text/html;charset=utf-8");
               //1、response调用getRequestDispatcher对象,从而获取调度对象
               RequestDispatcher other = request.getRequestDispatcher("/request/FServlet");
               //2、其他的Servlet调用forward进行转发请求,调用include方法进行转发包括
                 //3、进行转发请求之前,利用response获取对应的流对象,然后书写对应的响应头和实体数据
               response.setHeader("aaa","AAA");//当前Servlet中设置响应头,再进行请求转发,那么在新的Servlet不会清空当前Servlet设置的响应头,这就是留头
               //发送响应数据
               PrintWriter pw = response.getWriter();
               /*
               如果在EServlet中写这样的实体数据,然后在进行转发请求,那么并不会
               发送留头不流体的情况。
               for(int i = 0; i < 1024 * 24 + 1; ++i){
                   pw.write("this is EServlet");
               }*/
               pw.write("这是发送请求转发和包括的EServlet");//EServlet中发送实体数据,之后进行请求转发,那么新的Servlet就会清空当前Servlet中发送的实体数据,这就是不留体。
               other.forward(request,response);
           }
       }
       
       public class FServlet extends HttpServlet {
           @Override
           protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               //演示转发请求和转发包括
               //书写对应的实体数据,这时候并没有设置响应编码,所以如果输出的是中文,会发生乱码
               response.setContentType("text/html;charset=utf-8");//设置响应编码
               System.out.println("this is FServlet");
               response.setHeader("aaa","BBB");
               PrintWriter writer = response.getWriter();
               writer.println("这是请求转发和包括的FServlet");
       
         }
  }

测试结果:
在这里插入图片描述

如果在上面的EServlet中,进行的是请求包括,即other.include(request,response),那么对应的测试结果为:
在这里插入图片描述
所以上面2张图片可以知道,请求转发拥有留头不留体的特征,而请求包括则留头又留体

  • 请求转发和重定向的区别
    1、请求转发中地址栏并没有发生变化,而重定向的地址栏则发生了变化。也即是说请求转发中客户端只发送了1次请求,请求转发中的多个Servlet使用同一个请求,而重定向中则客户端发送了多个请求
    2、请求转发中只能向当前项目的其他Servlet进行转发,而重定向则可以向其他项目的Servlet进行重定向
    3、因为请求转发中多个Servlet使用的是同一个请求,而重定向则需要客户端发送多个请求,所以请求转发的效率比重定向的要高

编码问题

编码问题主要分为了响应编码和请求编码以及URL编码.

  • 响应编码
    由于服务端一般使用的是iso编码,而客户端则一般使用的是gbk编码。此时iso不可以识别中文,所以发送出去的数据是乱码,然后又因为服务端和客户端的编码不同,乱码会更加严重。
    所以服务端需要通过setCharacterEncoding(encode)来设置服务端的编码为encode,例如setCharacterEncoding(“utf-8”)来设置服务端的编码为utf-8,
    虽然utf-8,gbk是可以识别中文的,但是如果服务端的编码是utf-8,那么会因为两个端点的编码不同而导致乱码。所以服务端需要告知客户端自己使用的编码。所以服务端通过setHeader(“Content-Type”,“text/html;charset=utf-8”),这个语句不仅可以设置服务端的编码为utf-8,同时告诉了客户端服务端所使用的编码为utf-8,那么客户端就会自动使用对应得编码进行解码了,这样就不会出现乱码了。
    而setHeader(“Context-Type”,“text/html;charset=utf-8”)的快捷方式为:setContentType(“text/html;charset=utf-8”)
    ;
  • 请求编码
    请求主要分为 页面中的超链接和表单进行提交数据、地址栏URL这2中情况。
    而对于第一种情况,我们首先通过浏览器发送请求,才会得到一个页面。而这个页面(html文件)是utf-8的编码,尽管响应头中并没有Content-Type:text/html;utf-8,但是这个html文件中的语句已经设置了当前的页面的编码是utf-8了。那么通过超链接,或者表单发送出去的都是utf-8编码。而此时由于服务端使用的编码是iso,从而会发生乱码
    所以分2种情况:
    1. GET请求(即超链接):
      首先需要利用iso-8859-1进行回编,然后再利用utf-8进行重编
    2. POST请求:
      直接利用request.setCharacterEncoding(“utf-8”),然后再获取对应参数的值即可.但是需要保证再设置编码之后才可以获取对应参数的值,否则,如果在设置编码之前,调用了getParameter获取参数的值的话,那么哪怕有写了setCharacterEncoding,也不会生效的
 public class BServlet extends HttpServlet {
             @Override
             protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                 //1、调用getParameter来获取对应参数的值
                 String xxx = request.getParameter("xxx");
                 String yyy = request.getParameter("yyy");
                 //2、利用iso进行回编
                 byte[] bytes = xxx.getBytes("iso-8859-1");
                 byte[] bytes1 = yyy.getBytes("iso-8859-1");
                 //3、利用utf-8进行重编
                 xxx = new String(bytes, "utf-8");
                 yyy = new String(bytes1,"utf-8");
                 System.out.println("xxx的值为: " + xxx);
                 System.out.println("yyy的值为: " + yyy);
             }
         
             @Override
             protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                 /*
                 对于post请求,只需要将调用setCharacterEncoding为
                 utf-8,然后就可以直接获取对应参数的值了,注意是request来调用setCharacterEncoding,而不是response
                 但是需要注意的是,需要保证request调用setCharacterEncoding放在getParameter的前面
         
                 */
                 request.setCharacterEncoding("utf-8");
                 String username = request.getParameter("username");
                 String[] hobbies = request.getParameterValues("hobby");
                 System.out.println(username);
                 System.out.println(Arrays.toString(hobbies));
             }
 }

对应的encoding.html文件(在web目录下):

  <!DOCTYPE html>
    <html lang="en">
         <head>
             <meta charset="UTF-8"><!--设置客户端页面编码的形式为UTF-8-->
             <title>encoding.html</title>
         </head>
         <body>
	         <a href="/encoding/BServlet?xxx=张三&yyy=李四">通过链接来提交表单</a><br>
	         <form action="/encoding/BServlet" method="post">
	             姓 名: <input type="text" name="username" value="王五"><br>
	             密 码: <input type="password" name="password" value="123di"><br>
	             爱 好: <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>
   </html>

测试结果:
在这里插入图片描述

  • URL编码
    什么是URL编码,是客户端和服务端之间为了网络安全的编码,例如localhost:8080/username=张三&address=北京,这时候将参数的值能够完全显示出来,显然很容易被窃取数据,安全性不高,所以就出现了URL编码,它的作用就是将中文转成%后面跟随2位的16进制。
      URLEncoder.encode(String string,code);//code是对应的编码。调用encode实现URL编码
      URLDecoder.decode(String string,decode);//code是对应的编码。调用decode实现URL解码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值