博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web---字节输出流和字符输出流的共存问题、转发、重定向、请求包含知识点讲解...
阅读量:7022 次
发布时间:2019-06-28

本文共 14115 字,大约阅读时间需要 47 分钟。

本章博客的知识点:

1、字节输出流和字符输出流的共存问题

2、转发时,两个servlet都输出信息的问题
详细知识,见OneServlet和TwoServlet源代码中的注释
转发:传参,访问顺序(doGet还是doPost)
3、重定向:传参,访问顺序(doGet还是doPost)
4、请求包含:传参,访问顺序(doGet还是doPost)

有些演示,不怎么好分段用博客写处理,如果想加深理解的,最好自己取写一遍。

1、字节输出流和字符输出流的共存问题

index.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>    
字节输出流和字符输出流的共存问题

web.xml:

OutServlet
cn.hncu.servlet.OutServlet
OutServlet
/servlet/OutServlet
index.jsp

OutServlet.java:

package cn.hncu.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class OutServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //1、用字节输出流向客户端写信息 ServletOutputStream out = response.getOutputStream();//获取字节输出流 out.print("HELLO--doGet");//全部写英文是没有问题的 //out.print("你好");//500错误。出异常,因为内部是用iso8859-1读取,已经写死了,因此中文不行 out.write("你好".getBytes("utf-8"));//如果中文要用字节流输出,用write(byte[])方法,而且最好给编码方式 //2、同时用字符输出流向客户端写信息-也是出现500错误。 PrintWriter out2 = response.getWriter(); out2.print("hello,你好"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //1、用字节输出流向客户端写信息 ServletOutputStream out = response.getOutputStream();//获取字节输出流 out.print("HELLO--doGet");//全部写英文是没有问题的 //out.print("你好");//500错误。出异常,因为内部是用iso8859-1读取,已经写死了,因此中文不行 out.write("你好".getBytes("utf-8"));//如果中文要用字节流输出,用write(byte[])方法,而且最好给编码方式 //2、同时用字符输出流向客户端写信息-也是出现500错误。 PrintWriter out2 = response.getWriter(); out2.print("hello,你好"); }}

小总结:

大家自己写的时候,注意知道把哪里注释了,同时写了response.getOutputStream();//获取字节输出流和response.getWriter();-是不能共存的,也就是说,只能写其中一个!!!

2、转发时,两个servlet都输出信息的问题、传参,访问顺序(doGet还是doPost)

详细知识,见OneServlet和TwoServlet源代码中的注释

index.jsp:

转发时,两个servlet都输出信息的问题、传参问题、访问顺序问题

web.xml:

OneServlet
cn.hncu.servlet.OneServlet
TwoServlet
cn.hncu.servlet.TwoServlet
OneServlet
/servlet/OneServlet
TwoServlet
/servlet/TwoServlet

OneServlet.java:

package cn.hncu.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.RequestDispatcher;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class OneServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("你好...OneServlet..."); //out.flush();//Tomcat对于同response,只输出一次(把缓存中的内容刷出去)。刷了(close也一样),流就关闭了,下面的转发就无法进行了,因为此时response已经提交了(整个转发链只会响应一次,即提交了) //传参---设置属性(只要key不同,随便存几个)---放入request对象中 request.setAttribute("age", "23-OneServlet"); RequestDispatcher rd = request.getRequestDispatcher("/servlet/TwoServlet"); rd.forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("你好...OneServlet..."); //out.flush();//Tomcat对于同response,只输出一次(把缓存中的内容刷出去)。刷了(close也一样),流就关闭了,下面的转发就无法进行了,因为此时response已经提交了(整个转发链只会响应一次,即提交了) //传参---设置属性(只要key不同,随便存几个)---放入request对象中 request.setAttribute("age", "23-OneServlet"); RequestDispatcher rd = request.getRequestDispatcher("/servlet/TwoServlet"); rd.forward(request, response); }}

TwoServlet.java:

package cn.hncu.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class TwoServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");//如果前一个转发过来的Servlet已经设了,可以不用再写        PrintWriter out = response.getWriter();        out.println("get...
"); out.print("周末愉快。。。
"); //第二个servlet会先把缓存中之前的内容情空,然后再把当前servlet的输出内容写入缓存,刷出去。 String name = (String) request.getAttribute("age"); out.print("name:"+name+"
"); out.flush();//写在这里是没有什么影响的 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8");//如果前一个转发过来的Servlet已经设了,可以不用再写 PrintWriter out = response.getWriter(); out.println("post...
"); out.print("周末愉快。。。
"); //第二个servlet会先把缓存中之前的内容情空,然后再把当前servlet的输出内容写入缓存,刷出去。 String name = (String) request.getAttribute("age"); out.print("name:"+name+"
"); out.flush();//写在这里是没有什么影响的 }}

小总结:

转发时,两个servlet都输出信息的问题

详细知识,见OneServlet和TwoServlet源代码中的注释
传参,访问顺序(doGet还是doPost) —转发是共享同一个request和同一个response对象的
1)第一个是doGet,第二个走的也是doGet
2)第一个是doPost,第二个走的也是doPost
(因为request传过来的参数一样,访问方式也是一样的)
3)传参:可以通过request.setAttribute()设置,通过request.getAttribute()获取 —doGet或doPost都一样

3、重定向:传参,访问顺序(doGet还是doPost)

index.jsp:

重定向时,两个servlet都输出信息的问题、传参问题、访问顺序问题

web.xml:

RedirOneServlet
cn.hncu.servlet.RedirOneServlet
RedirTwoServlet
cn.hncu.servlet.RedirTwoServlet
RedirOneServlet
/servlet/RedirOneServlet
RedirTwoServlet
/servlet/RedirTwoServlet

RedirOneServlet.java:

package cn.hncu.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class RedirOneServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("11111111111");//这是一个无效的输出,我们看不到!! response.sendRedirect("/myServletDemo4/servlet/RedirTwoServlet"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("11111111111");//这是一个无效的输出,我们看不到!! //out.flush(); //如果刷了,后面就不能故去了。 String name = request.getParameter("name"); System.out.println("11111para-name:"+name);//这个也只有这里能接收到,如果想要传过去,得通过 地址栏+?+name= 的方式,如最后一行 request.setAttribute("age", 23);//这一句是没用的,对方收不到! //response.sendRedirect("/myServletDemo4/servlet/RedirTwoServlet"); response.sendRedirect("/myServletDemo4/servlet/RedirTwoServlet?name="+name+"&age=23"); }}

RedirTwoServlet.java:

package cn.hncu.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class RedirTwoServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");        PrintWriter out = response.getWriter();        out.print("doget........22222222
"); String name = request.getParameter("name"); out.print("2222para-name:"+name); String age = request.getParameter("age"); out.print("
2222para-age:"+age); //得到地址栏?号后的属性值 Integer age2 = (Integer) request.getAttribute("age"); out.print("
attr-age:"+age2);//null. web.xml 中没有设置 } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print("doget........22222222
"); }}

小总结:

两个servlet都输出信息的问题,这里和转发的情况其实可以理解是相同的,你第一个servlet如果out调用flush(),一样的,不会再重定向到后面的第二个servlet中去了。

1)无论第一个是doGet还是doPost,第二个走的都是doGet

(可以理解成:通过地址栏访问的)
2)传参:第二个servlet中的request和第一个是完全不同的对象,因此无法通过:request.setAttribute()和request.getAttribute() 实现传参。

3)第二个servlet中是无法通过request.getParameter()的方式获取页面提交的参数数据

4)重定向方式下,如果要进行传参,可采用:在地址栏的url后添加类似如下的格式传参:?name=Jack&age=23

注意,采用地址栏url传参的方式,在浏览器地址栏是能够看到的,因此要注意隐私(安全)问题—如果有隐私参数,那么要加密!!!

5)转发只能在站内进行(路径默认在项目内,即路径不用带项目名),重定向可以在站外进行(如果是站外路径要带“http://”开头,站内路径要带项目名)。如果非要项目之间(站外)进行跳转,那么必须要选择重定向。

4、请求包含:传参,访问顺序(doGet还是doPost)

index.jsp:

请求包含时,两个servlet都输出信息的问题、传参问题、访问顺序问题

web.xml:

IncludeOneServlet
cn.hncu.servlet.IncludeOneServlet
IncludeTwoServlet
cn.hncu.servlet.IncludeTwoServlet
IncludeOneServlet
/servlet/IncludeOneServlet
IncludeTwoServlet
/servlet/IncludeTwoServlet

IncludeOneServlet.java:

package cn.hncu.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.RequestDispatcher;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class IncludeOneServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");        PrintWriter out = response.getWriter();        out.print("");        out.print("Include111111..doGet...");        //传参,和转发时一样的!        request.setAttribute("age", 25);        RequestDispatcher rd = request.getRequestDispatcher("/servlet/IncludeTwoServlet");        rd.include(request, response);        //它的机制可理解成函数调用。相当于把第二个servlet的doGet()方法中的代码拷到这里来运行。        //后面的还可以继续运行!!!        out.print("
Include11111...daGet...请求包含之后!"); out.print(""); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); out.print(""); out.print("Include111111..doPost..."); //传参,和转发时一样的! request.setAttribute("age", 25); RequestDispatcher rd = request.getRequestDispatcher("/servlet/IncludeTwoServlet"); rd.include(request, response); //它的机制可理解成函数调用。相当于把第二个servlet的doPost()方法中的代码拷到这里来运行。 //后面的还可以继续运行!!! out.print("
Include11111...doPost...请求包含之后!"); out.print(""); }}

IncludeTwoServlet.java

package cn.hncu.servlet;import java.io.IOException;import java.io.PrintWriter;import javax.servlet.RequestDispatcher;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class IncludeTwoServlet extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        response.setContentType("text/html;charset=utf-8");        //因为上一个servlet已经设过,这里可以不设        PrintWriter out = response.getWriter();        //out.print("");        out.print("
Include222222中文...doGet"); //接参 Integer age = (Integer) request.getAttribute("age"); out.print("
Include222222...doGet...:"+age); //下面这两句会导致无穷递归 //RequestDispatcher rd = request.getRequestDispatcher("/servlet/IncludeOneServlet"); //rd.include(request, response); //out.print(""); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); //因为上一个servlet已经设过,这里可以不设 PrintWriter out = response.getWriter(); // out.print("
Include222222中文...doPost"); //接参 Integer age = (Integer) request.getAttribute("age"); out.print("
Include222222...doPost...:"+age); }}

小总结:

1)两个servlet的输出都有效!—中途调用flush,流不会关闭,后续的输出都会执行。如果在第一个servlet中执行了out.close(),那么后续的输出(无论是第一还是第二个servlet)都不会执行,但程序不会出异常!!!!

2)第一个是doGet,第二个走的也是doGet
3)第一个是doPost,第二个走的也是doPost
4)对于请求包含,第二个servlet在执行完之后,还会回到第一个servlet的rd.include()这行代码之后。
5)传参方面,和转发是完全一样的,因为都是共享同一个request和同一个response.
6)页面输出时,注意html标签不要输出冲突,如:在第一个servlet中输出了“<html><body>”和“</body></html>”,同时在第二个servlet中也输出这些标记。这样会出现html标记嵌套冲突!!
※重定向和转发:跳转之后不会回到原来的那个servlet中。
而“请求转发”在跳转之后会回到原来servlet的“rd.include()”这句代码之后继续执行。

演示:

可以看到,客户端只请求了一次!!!转发是请求两次的。

如果2个服务器都向客户端输出了<html><body> </body></html>

会出现:

你可能感兴趣的文章
nignx
查看>>
阿里的settings.xml
查看>>
jdbc
查看>>
反射知识点
查看>>
谷歌明确Fuchsia并非基于Linux内核
查看>>
Jenkins的安装和使用(Centos7)
查看>>
Red Hat Linux的学习
查看>>
java关于安卓,苹果输入表情数据库处理
查看>>
oracle与db2分区的区别
查看>>
如何快速把一个11g数据库插入到12c cdb中去?
查看>>
缓存架构设计细节二三事
查看>>
mybatis链接数据库 返回自增主键
查看>>
SpringBoot简化部署
查看>>
yml使用
查看>>
3.04-Miniui总结(一)
查看>>
Hadoop-工作流图解
查看>>
js基础 局部变量和全局变量 作用域链 形参是局部变量
查看>>
nexus
查看>>
springboot 使用jsp
查看>>
Tomcat_JDK部署、zrlog安装和nginx代理Tomcat
查看>>