1、字节输出流和字符输出流的共存问题
1.1字节输出流*
//这种方式内部默认用iso8859-1编码输出,不能输出中文
(1) response.getOutputStream().println(“abcd”);
//如果要输出中文,要下面这种方式
(2) response.getOutputStream().write(“中国”.getBytes(“utf-8”));
1.2字符输出流
输出之前,一般先设编码
response.setContentType(“text/html;charset=utf-8”);
response.getWriter().println(“中国”);
注意,有个细节,同一个servlet中,字符输出流和字节输出流只能用一个,否则会报错!
2、转发时,两个servlet都输出信息的问题
转发:request.getRequestDispatcher(“/servlet路径”).forward(request,response);
转发时request和response对象共享,两次servlet的请求方式一致,即原来为doGet(),转发时也为doGet(),原来为doPost(),转发时也为doPost()。
转发时,response只响应一次,如果两个servlet都输出信息,第二个servlet输出会覆盖第一个servlet输出,如果第一个servlet强行刷流或关流,response会提前响应,导致转发失效。如果非要实现这个功能,可利用传参技术。代码如下:
第一个servlet传参:request.setAttribute(“name”,”Jack”);
第二个servlet接参:String name = (String)request.setAttribute(“name”);
3、重定向
重定向:response.sendRedirect(“/项目名/servlet路径”);
转发时,无论第一个请求为doGet()方式还是doPost()方式,第二次请求都是doGet()方式。第二次相当于地址栏直接请求,参数信息会显示在地址栏中。
由于两次请求的request和response对象都不同,无法通过类似request.setAttribute(“name”,”Jack”);request.setAttribute(“name”);的方式传参,并且第二次请求的request无法通过request.getParameter()的方式获取前台页面数据。如果非要传参,可在第一个Servlet中通过response.sendRedirect(“/项目名/servlet路径?参数名=’参数’”);,第二个Servlet中通过request.getParameter()的形式接参。
4、请求包含
请求包含:request.getRequestDispatcher(“/servlet路径”).include(request,response);
这种方式和转发差不多,request和response对象共享,两次servlet的请求方式一致,即原来为doGet(),转发时也为doGet(),原来为doPost(),转发时也为doPost()。但也有区别,如果两个Servlet都输出信息,两个输出信息都有效,这种方式类似于函数调用一样,第二个Servlet执行完后,会继续返回第一个servlet,继续执行request.getRequestDispatcher(“/servlet路径”).include(request,response);之后的代码。根据这一特性,有个小细节要注意,servlet自动生成时,应删掉第二servlet的标签,避免影响到html的DOM结构,引起不必要的错误。
最后做一个小的总结:转发和请求包含只能在站内进行(路径默认在项目内),重定向可以在站外进行(如果是站外,路径要以”http://”开头,如果是站内,路径要带项目名),像一般的支付项目,必须用重定向方式向站外跳转,而且根据安全和隐私原则,参数要加密。