文章目录
- 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"));
输出结果:
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>
展示结果:
后端代码:
//1.queryString访问路径 :request?username=abc&password=123
System.out.println("username: "+req.getParameter("username"));
System.out.println("password: "+req.getParameter("password"));
后端输出:
点击get链接url变为:
注意: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>
展示结果:
后端代码:
//2.表单格式:body中的数据,格式和queryString一样
//注意:body中的内容也是有编码格式的,需要设置一下才能正常显示,不加输入中文时会产生乱码
req.setCharacterEncoding("utf-8");//设置body解析的编码格式
System.out.println("username: "+req.getParameter("username"));
System.out.println("password: "+req.getParameter("password"));
提交后会发现方法不允许:
那么我们这里就需要在不改doGet方法的前提下,同时也要支持post方法,怎么做呢?
//既支持get,也支持post方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);//逻辑一样,就调用doGet方法
}
后端输出:
fiddler抓包结果:
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>
同时把后端这里修改:
提交结果后后端输出:
fiddler抓包结果:
重点:http请求数据,存放的位置
- url queryString
- body(多种类型)
3.getPart
获取form-data格式中,上传的文件
假如上传文件直接采用getParameter()来获取,是获取不到的:
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"));
打印出来的二进制数据:
(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"));
}
}
后端输出结果:
fiddler抓包显示:
其实,我们拿到整个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;
}
}
}
后端输出:
一般转换json字符串为自定义类型,但需要注意: json中的键在java类型必须有对应的成员变量名,否则会报错