文章目录

  • 1.了解方法
  • 2.getParamter
  • 1.获取url QueryString中的数据
  • 2.获取body中表单格式
  • 3.获取form-data中的简单数据类型的数据
  • 3.getPart
  • 4.getInputStream

1.了解方法

System.out.println("请求协议名:"+req.getProtocol());
System.out.println("请求方法:"+req.getMethod());
System.out.println("应用上下文路径/应用名:"+req.getContextPath());
System.out.println("资源路径/servletPath:"+req.getServletPath());
System.out.println("请求头中键为Host的值:"+req.getHeader("Host"));

输出结果:

ServertRequest获取请求路径_前端

2.getParamter

通过键获取值:1.queryString 2.表单格式,body 3.form-data格式简单的类型

1.获取url QueryString中的数据

前端代码:

<h3>get with query string</h3>
<!-- 当前页面访问的路径:/[contextPath应用上下文路径]/request.html,
需要跳转到/[contextPath]/request -->
<!-- 也可以直接在url输入链接跳转后相同的url绝对路径来访问 -->
<a href="request?username=abc&password=123">get</a>

展示结果:

ServertRequest获取请求路径_java_02

后端代码:

//1.queryString访问路径 :request?username=abc&password=123
System.out.println("username: "+req.getParameter("username"));
System.out.println("password: "+req.getParameter("password"));

后端输出:

ServertRequest获取请求路径_java_03


点击get链接url变为:

ServertRequest获取请求路径_java_04


注意:http请求时,url会进行编码,获取queryString中的中文,空格,特殊字符就需要解码

演示:form表单提交没有设置请求方法,默认是get,会把form中的控件以name为键,
输入选择的内容为值,设置到queryString,和上边达到相同的效果

前端代码:

<form action="request">
    <input type="text" name="username" placeholder="输入用户名">
    <br>
    <input type="password" name="password" placeholder="输入密码">
    <br>
    <input type="submit" value="提交">
</form>

社区版是中文正常显示,但我们写代码要注意可能有乱码的情况

2.获取body中表单格式

前端代码:

<h3>表单格式:/request</h3>
<form action="request" method="post">
    <input type="text" name="username" placeholder="输入用户名">
    <br>
    <input type="password" name="password" placeholder="输入密码">
    <br>
    <input type="submit" value="提交">
</form>

展示结果:

ServertRequest获取请求路径_java_05


后端代码:

//2.表单格式:body中的数据,格式和queryString一样
//注意:body中的内容也是有编码格式的,需要设置一下才能正常显示,不加输入中文时会产生乱码
req.setCharacterEncoding("utf-8");//设置body解析的编码格式
System.out.println("username: "+req.getParameter("username"));
System.out.println("password: "+req.getParameter("password"));

提交后会发现方法不允许:

ServertRequest获取请求路径_前端_06


那么我们这里就需要在不改doGet方法的前提下,同时也要支持post方法,怎么做呢?

//既支持get,也支持post方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req,resp);//逻辑一样,就调用doGet方法
}

后端输出:

ServertRequest获取请求路径_http_07


fiddler抓包结果:

ServertRequest获取请求路径_java_08

3.获取form-data中的简单数据类型的数据

前端代码:

<h3>form-data格式:/form-data-servlet</h3>
<form action="form-data-servlet" enctype="multipart/form-data" method="post">
    <input type="text" name="username" placeholder="输入用户名">
    <br>
    <input type="password" name="password" placeholder="输入密码">
    <br>
    <input type="submit" value="提交">
</form>

同时把后端这里修改:

ServertRequest获取请求路径_http_09


提交结果后后端输出:

ServertRequest获取请求路径_数据_10


fiddler抓包结果:

ServertRequest获取请求路径_java_11


重点:http请求数据,存放的位置

  • url queryString
  • body(多种类型)

3.getPart

获取form-data格式中,上传的文件

假如上传文件直接采用getParameter()来获取,是获取不到的:

ServertRequest获取请求路径_java_12


ServertRequest获取请求路径_前端_13


form-data中上传的文件,需要通过getPart来获取,getParameter无法获取

简单类型的数据其实也可以使用getPart获取,但还需要调用Part对象来获取内容,比较复杂
(1)可以读取:通过Part对象的输入流读

Part head=req.getPart("head");
//获取上传文件的二进制数据,转换为字符串打印
InputStream is = head.getInputStream();//获取输入流(里边包含了数据)
//输入流.available返回包含的数据长度
byte[] bytes = new byte[is.available()];
//从输入流中,把数据读取到byte[]中,字节数组对象就有了这些数据
is.read(bytes);
System.out.println(new String(bytes,"utf-8"));

打印出来的二进制数据:

ServertRequest获取请求路径_ajax_14


(2)也可以直接把客户端上传的文件,保存在服务端本地(不读取,直接保存)

注意不能使用上边的代码读取后再保存

//了解:getSubmittedFileName是获取上传文件的名称
//注意:如果这个路径已经有这个文件就会报错
head.write("D://"+head.getSubmittedFileName());

成功之后就会在对应的目录下找到刚才保存的图片

4.getInputStream

获取请求正文body的数据(输入流中包含了这些数据),不管什么格式,只要是在body中,都可以获取到
只是表单格式,没有必要使用这个方式来获取(麻烦,还要自己解析里边的多组键值对)
常用的场景: json格式

前端代码:

<body>
    <h3>ajax提交json格式</h3>
    <input type="text" id="ajax_username" placeholder="输入用户名">
    <br>
    <input type="password" id="ajax_password" placeholder="输入密码">
    <br>

    <button onclick="ajaxSubmit()">提交</button>
</body>
<script>
    function ajaxSubmit(){
        let username = document.querySelector("#ajax_username");
        let password = document.querySelector("#ajax_password");
        let json = {
            username: username.value,//键为username,值为对象的value属性
            password: password.value,

        };
        ajax({
            url: "ajax-json-servlet",
            method: "post",
            //body上为json格式的字符串
            contentType: "application/json",
            //JSON.stringify是将一个json对象序列化为一个字符串,格式是json格式
            body: JSON.stringify(json),
            callback: function(status,resp){
                alert("后端返回的内容: "+resp);
            },
        });
    }
    //前面封装的ajax函数
    function ajax(args){//var ajax = function(){}
        let xhr = new XMLHttpRequest();
        //设置回调函数
        xhr.onreadystatechange = function(){
            //4:客户端接收到响应后回调
            if(xhr.readyState == 4){
                // 回调函数可能需要使用响应的内容,作为传入参数
                args.callback(xhr.status,xhr.responseText);
            }
        }
        xhr.open(args.method,args.url);
        // 如果args中,Content-Type属性有内容,就设置Content-Type请求头
        if(args.contentType){//js中,除了判断boolean值,还可以判断字符串,对象等,有值就为true
            xhr.setRequestHeader("Content-Type",args.contentType);
        }
        //如果args中,设置了body请求正文,调用send(body)
        if(args.body){
            xhr.send(args.body);
        }else{//如果没有设置,调用send()
            xhr.send();
        }
    }
</script>

后端代码:

@WebServlet("/ajax-json-servlet")
public class AjaxJsonServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");//获取请求body数据,先设置编码
        //json是使用这个api比较典型的场景
        InputStream is = req.getInputStream();
        //body的长度,在请求头Content-Length已经标识
        int len = req.getContentLength();//也可以通过getHeader("Content-Length")获取,只是返回的是字符串相对麻烦一点
        byte[] bytes = new byte[len];
        is.read(bytes);
        System.out.println("获取的json数据: "+new String(bytes,"utf-8"));
    }
}

后端输出结果:

ServertRequest获取请求路径_数据_15


fiddler抓包显示:

ServertRequest获取请求路径_http_16


其实,我们拿到整个json字符串也不方便使用,比如要判断账号密码是否正确

常用的方式: 使用第三方库,可以把json字符串,转换为一个java对象,还可以把一个java对象,转换为json字符串(响应的时候就有用)

前端代码:

@WebServlet("/ajax-json-servlet")
public class AjaxJsonServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        InputStream is = req.getInputStream();
        User user = mapper.readValue(is,User.class);
        System.out.println("获取的json字符串转换的user对象: "+user);
    }

    //静态内部类:包含在两个类{}内,使用和普通类一样
    //把json字符串转换为java对象,需要某个键的名称和成员变量名一样(类型也是)
    static class User{
        private String username;
        private String password;

        @Override
        public String toString() {
            return "User{" +
                    "username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }

        //再提供getter和setter方法
        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }
}

后端输出:

ServertRequest获取请求路径_ajax_17


一般转换json字符串为自定义类型,但需要注意: json中的键在java类型必须有对应的成员变量名,否则会报错