22-05-21 西安 javaweb(07) HttpServletRequest和HttpServletResponse、转发与重定向、web应用的路径问题、解决中文乱码问题

HttpServletRequest和HttpServletResponse

它俩分别是用来获取请求报文,设置响应报文!


HttpServletRequest

HttpServletRequest封装了请求报文,我们可以从中获取到的内容有:

1.获取请求参数
2.获取请求行(展示当前请求的信息)
3.获取请求头信息
4.请求转发

request获取请求参数

  1. String request.getParameter(name):获取浏览器传输的单个的请求参数
  2. String[] request.getParameterValues(name):获取浏览器传输的多个同名的请求参数的值的数组

准备一个页面用于提交用户名、密码、爱好

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello,tomcat</h1>
<form action="FirstServlet" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    爱好:<input type="checkbox" name="hobby" value="AA">AA
    <input type="checkbox" name="hobby" value="BB">BB
    <input type="checkbox" name="hobby" value="CC">CC
    <input type="checkbox" name="hobby" value="CC">DD
    <input type="checkbox" name="hobby" value="CC">EE<br>
    <input type="submit" value="提交"><br>
</form>
</body>
</html>

页面效果如下:

别问我问什么选CD????单纯喜欢这俩个字母而已,咦~

public class FirstServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, UnsupportedEncodingException {
        // 不管是get还是post都能获取
        // 获取浏览器传输的单个请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //获取浏览器传输多个同名的请求参数
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("username:"+username+",password:"+password+",hobby:"+ Arrays.toString(hobbies));
    }
}

控制台打印结果:


HttpServletRequest解决请求参数中文乱码问题

request.setCharacterEncoding("UTF-8");

因为编码不一致:浏览器有浏览器的编码,服务器有服务器的编码。
tomcat8.5 解决了get请求的中文乱码问题,tomcat 7 get请求有中文乱码问题

获取请求参数之前设置,在设置编码之前不能获取任何获取请求参数才有效
先设置编码过滤器,再来设置获取请求参数过滤器

public class FirstServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, UnsupportedEncodingException {
        //解决中文乱码
        request.setCharacterEncoding("UTF-8");
        //获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("username:"+username+",password:"+password+",hobby:"+ Arrays.toString(hobbies));
    }
}

中文乱码问题得到解决:


request获取请求相关信息

request.getContextPath();//获取当前web应用上下文路径

public class ServletMM extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        获取当前web应用上下文路径
        String contextPath = request.getContextPath();
//        获取协议
        String scheme = request.getScheme();
//        获取服务器的端口号
        int serverPort = request.getServerPort();
//        获取服务器ip地址
        String serverName = request.getServerName();
//        获取发送请求的统一资源定位符(在网络中的地址)
        StringBuffer requestURL = request.getRequestURL();
//        获取发送请求的统一资源标识符  (资源在服务器的地址,上下文路径下的资源路径)
        String requestURI = request.getRequestURI();

        System.out.println("统一资源定位符:"+requestURL.toString());
        System.out.println("统一资源标识符:"+requestURI);
    }
}


request 获取请求头信息

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取当前请求的来源路径
        String cookie = request.getHeader("cookie");//参数写请求头的键,键不区分大小写
        System.out.println("cookie:"+cookie);
    }

request获取请求体(扩展)
request.getReader()//获取字符输出流,缓冲流可以一次读一行

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        BufferedReader bufferedReader = request.getReader();
        //获取字符输出流,缓冲流可以一次读一行
        String line = bufferedReader.readLine();
        System.out.println(line);
    }


request请求转发

是将当前的请求传递到下一个资源继续进行处理,是响应浏览器的一种方式。

request.getRequestDispatcher("/success.html").forward(request,response);//请求转发

请求转发特点:
请求转发时浏览器地址栏没有发生变化,浏览器只发送了一次请求,最终实现的页面跳转发生在服务器内部,浏览器是不知道的!

这里/success.html,“/”可以加也可以不加,加了之后是绝对路径,因为是请求转发,所以/是由服务器解析的,这个路径问题一会专门讲。用老师的话说:路径问题是个大问题!

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        请求转发:是将当前的请求传递到下一个资源继续进行处理
//        交给页面处理请求就是展示给用户
        request.getRequestDispatcher("/success.html").forward(request,response);
    }

请求转发举例

理论上我请求的是ServletMM,实际上给我转发到了success.html(也即在服务器内部给我跳转到了success.html,页面显示的最终效果就是success.html的内容)。

且我们发现请求转发时浏览器地址栏没有发生变化。也就是说,既然显示的是success.html页面的内容,地址栏应该像第二张图那样才对呀,可是事实上请求转发的地址栏就是第一张图那样。应证了那句:请求转发是在服务器内部跳转的。


HttpServletResponse

封装服务器发送到浏览器的响应报文,因此可以通过此对象设置当前响应相关的信息

     PrintWriter中的write()和print()会把数据存储在响应体响应给浏览器
     区别是:print可以将任意类型输出给浏览器,它俩效果是一样的。

将任意类型输出给浏览器

//字符输出流,输出文本  标签会被浏览器解析
response.getWriter().print("<h1>Tomorrow is another day</h1>");
//字节输出流,输出文件
ServletOutputStream outputStream = response.getOutputStream();
// writer.write("helloworld");

如向浏览器发送内容  <h1>Tomorrow is another day</h1>,看的出来h1标签也是被解析了的


那要是向浏览器发送的内容中有中文呢?

如我要给浏览器发送    <h1>顺为凡,逆则仙</h1>,如下:

            //字符输出流,输出文本  标签会被浏览器解析
            response.getWriter().print("<h1>顺为凡,逆则仙</h1>");

这时候浏览器就蒙蔽了,,,解析成这个样子了:

解决响应到浏览器数据的乱码问题:

            //设置响应报文中存储数据的编码格式
            response.setCharacterEncoding("UTF-8");
            //设置浏览器解码格式,以文本形式存在的html,
            // 这一块忘记点进去setContentType去源码找text/html;charset=UTF-8
            response.setContentType("text/html;charset=UTF-8");
            //字符输出流,输出文本  标签会被浏览器解析
            response.getWriter().print("<h1>顺为凡,逆则仙</h1>");

效果很清晰:输出了我喜欢的玄幻小说之一《仙逆》的主旨

设置浏览器解码格式时也可以这么写,但是没必要,不推荐

response.setHeader("Content-Type", "text/html;charset=UTF-8");


重定向

重定向也可以跳转页面,它是浏览器发送2次请求,浏览器地址栏会发生变化。最终实现的页面跳转发生在浏览器端。

//由服务器通知浏览器再次发送请求跳转到重定向的路径
response.sendRedirect("success.html");


响应浏览器的3种方式

1.响应浏览器数据
2.请求转发
3.重定向

总结:业务逻辑处理成功使用重定向,业务逻辑处理失败使用请求转发

以下来自我自己的总结,在新的页面中有操作且有数据要带过去展示的话用请求转发,有操作但是没有数据带过去的情况下,用重定向。没有操作没有数据带过去的单纯跳转页面用转发。

补充:

有操作有数据也可以使用重定向, 这时你只要将数据存入到session中也是可以的.

没有操作没有数据带过去用 重定向和内部转发 都可以.用转发是因为转发可以访问WEB-INF目录下的资源


请求转发和重定向区别:

区别一:
转发时地址栏不变,即显示的是servlet地址,浏览器只发送一次请求,最终页面跳转发生在服务器端;重定向时地址栏改变,即显示最终重定向的地址,浏览器只发送2次请求,最终页面跳转发生在浏览器端

区别二:
WEB-INF下的页面具有隐藏性、安全性,浏览器不能直接访问,只有服务器才能访问,即只有请求转发才能访问到,重定向不能访问到。以后大部分情况,把页面放在WEB-INF下。不会把css,js放在WEB-INF下

区别三:
请求转发可以访问请求域中的数据,重定向不可以。
那是因为转发是浏览器发送的一次请求,request对象是同一个。重定向发送2次请求,2次请求对应2个request对象

登录失败,需要把错误信息共享在请求域中,这是因为另外俩种域对象太大了,所以业务逻辑处理失败使用转发。


相对路径和绝对路径

相对路径指目标资源相对于当前位置的路径

绝对路径

  1. static web中,绝对路径指目标资源在磁盘上的路径
  2. web application中,绝对路径指目标资源在服务器上的路径

相对路径的缺点对应绝对路径的优点 :
1、相对路径跟目标资源的位置和当前的位置有关,其中任何一个位置发生变化,则相对路径失效
2、相对路径跟目标资源的位置和当前的位置有关,在不同的位置访问同一个资源,没有统一的访问路径
3、相对路径在请求转发中不靠谱,因为相对地址会发生变化

对第3条的理解:在请求转发到的页面中,由于请求转发是浏览器发送的一次请求,因此地址栏中的地址不变,即访问的是servlet的地址,因此当前位置发生了变化,从而影响到页面中的相对路径


web application的绝对路径
很简单:就是”/“开头的路径。但是这个“/”分为服务器解析和浏览器解析

服务器解析的绝对路径中,/表示"http://localhost:8080/上下文路径"下开始访问
浏览器解析的绝对路径中,/表示"http://localhost:8080"下开始访问

服务器解析的绝对路径的2种情况:①web.xml中使用的绝对路径,②请求转发到的绝对路径

如url-pattern标签中的"/"       <url-pattern>/ServletMM</url-pattern>

浏览器解析的绝对路径的情况:①html页面中标签设置的绝对路径,② 重定向到的绝对路径


html页面中标签绝对路径3种处理方式

由于是浏览器所解析的绝对路径,所以缺失了上下文路径,有3种处理方式

方式1、手动添加上下文路径
方式2、base标签 
方式3、将web应用的上下文路径设置为"/"

第二种方式:

<base href="/day05_web/">

href里有俩个"/",后面那个"/"为什么写在base里,因为base标签不能作用于绝对路径的(以"/"开头的路径)

第三种方式:

"/" 由浏览器和服务器解析的绝对路径就是一样的了,实际项目就是这么用的

重定向到的绝对路径的处理方式:
在重定向到绝对路径前拼接request.getContextPath();

            System.out.println("上下文路径: "+request.getContextPath());
            //重定向由浏览器解析,要加上下文路径
            response.sendRedirect(request.getContextPath() + "/test.html");

浏览器重定向后展示的页面

 控制台输出上下文路径为:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值