> 文章列表 > servlet(2)—javaEE

servlet(2)—javaEE

servlet(2)—javaEE

1.获取请求数据

1.1开发前端发请求

ajax封装代码

// 参数 args 是一个 JS 对象, 里面包含了以下属性
// method: 请求方法
// url: 请求路径
// body: 请求的正文数据
// contentType: 请求正文的格式
// callback: 处理响应的回调函数, 有两个参数, 响应正文和响应的状态码
function ajax(args) {var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {// 0: 请求未初始化// 1: 服务器连接已建立// 2: 请求已接收// 3: 请求处理中// 4: 请求已完成,且响应已就绪if (xhr.readyState == 4) {args.callback(xhr.status, xhr.responseText)}}xhr.open(args.method, args.url);if (args.contentType) {xhr.setRequestHeader('Content-type', args.contentType);}if (args.body) {xhr.send(args.body);} else {xhr.send();}
}

html前端代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input id="u" type="text" placeholder="请输入账号"><br><input id="p" type="password" placeholder="请输入密码"><br><button onclick="send()">ajax get提交</button><script src="ajax.js"></script><script>var username = document.querySelector("#u");var password = document.querySelector("#p");function send() {ajax({method: "GET",url:"request/get?username="+username.value+"&password="+password.value,callback: function(status,resp){alert("响应状态码:"+status+",响应正文:"+resp)}})}</script>
</body>
</html>

1.2开发后端servlet

package org.example.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/request/get")
public class requestGet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");System.out.printf("username=%s,password=%s\\n",username,password);}
}

servlet(2)—javaEE

打印结果:
servlet(2)—javaEE

2.客户端发送请求

2.1ajax发请求

(1)8的获取请求数据使用的就是ajax发请求
(2)get方法的执行流程
①点击get提交按钮到绑定的点击事件
②执行绑定的点击事件的函数(ajax代码)
③执行后端代码
servlet(2)—javaEE
(2)可能出现的问题
①按钮点击以后没有反应,抓包解决
servlet(2)—javaEE

②没有发http请求,一定是前端代码的问题,开发者工具,源代码才是浏览器真正运行的代码解决
servlet(2)—javaEE

③抓包出现404,检查请求路径和服务端资源路径
servlet(2)—javaEE
请求路径:
绝对路径写法:
servlet(2)—javaEE

相对路径写法:
servlet(2)—javaEE

④出现405,方法不支持,检查后端代码,看是否提供对应的服务方法
servlet(2)—javaEE

servlet(2)—javaEE

2.2发送form表单格式的请求数据

前端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input id="u" type="text" placeholder="请输入账号"><br><input id="p" type="password" placeholder="请输入密码"><br><button onclick="send()">ajax form表单提交</button><script src="ajax.js"></script><script>var username = document.querySelector("#u");var password = document.querySelector("#p");function send() {ajax({method: "POST",url:"request/post",contentType: "application/x-www-form-urlencoded",body:"username="+username.value+"&password="+password.value,callback: function(status,resp){alert("响应状态码:"+status+",响应正文:"+resp)}})}</script>
</body>
</html>

后端代码:

package org.example.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/request/post")
public class requestFormAjax extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");System.out.printf("username=%s,password=%s\\n",username,password);}
}

抓包看到的请求正文的结果
servlet(2)—javaEE

2.3发送JSON格式的请求数据

前端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input id="u" type="text" placeholder="请输入账号"><br><input id="p" type="password" placeholder="请输入密码"><br><button onclick="send()">ajax json提交</button><script src="ajax.js"></script><script>var username = document.querySelector("#u");var password = document.querySelector("#p");function send() {// json对象var data = {username:username.value,password:password.value};ajax({method: "POST",url:"request/json",contentType: "application/json",// 将JSON对象转换为JSON字符串body: JSON.stringify(data),callback: function(status,resp){alert("响应状态码:"+status+",响应正文:"+resp)}})}</script>
</body>
</html>

servlet代码的第一种写法,了解就行

package org.example.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;@WebServlet("/request/json")
public class requestJSON1 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//接收请求body为json格式的数据,需要使用inputStreamInputStream is = req.getInputStream();//接收到的是字节流,需要使用字节字符转换流来转换InputStreamReader isr = new InputStreamReader(is, "UTF-8");//最终是:字符流(字节字符转换流(字节流))BufferedReader br = new BufferedReader(isr);String str;//读取一行到字符串,如果不为空,表示没有结束while ((str=br.readLine()) != null){System.out.println(str);}}
}

抓包看到的请求正文的结果
servlet(2)—javaEE
测试JSON在java中的使用:
引入依赖:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.11.3</version>
</dependency>

测试JSON在java中的使用

package org.example.servlet;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;public class textJSON {public static void main(String[] args) throws JsonProcessingException {// json反序列化:JSON字符串转java对象String json = "{\\"username\\":\\"in\\",\\"password\\":\\"123\\"}";// 需要使用Jackson框架提供的api来完成// 这个对象就是辅助完成JSON字符串和java对象相互转化ObjectMapper objectMapper = new ObjectMapper();// 可以转换为map,但是还是不但方便HashMap map = objectMapper.readValue(json,HashMap.class);System.out.println(map);//结果:{password=123, username=in}// 建议:自定义一个类型,成员变量名就是JSON字符串的键名,类型要保持一致User user = objectMapper.readValue(json,User.class);System.out.println(user);//结果:User{username='in', password='123'}}
}

用户类:

package org.example.servlet;public class User {private String username;private String password;@Overridepublic String toString() {return "User{" +"username='" + username + '\\'' +", password='" + password + '\\'' +'}';}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;}
}

servlet代码的第二种写法,也建议这样完成

package org.example.servlet;import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;@WebServlet("/request/json")
public class requestJSON2 extends HttpServlet {private static final ObjectMapper objectMapper = new ObjectMapper();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {//接收请求body为json格式的数据,需要使用inputStreamInputStream is = req.getInputStream();// json反序列化:将JSON字符串转化为java对象User user = objectMapper.readValue(is,User.class);System.out.println(user);}
}

2.4发送form-data格式的数据

前端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input id="u" type="text" placeholder="请输入账号"><br><input id="p" type="password" placeholder="请输入密码"><br><button onclick="send()">ajax form-data提交</button><script src="ajax.js"></script><script>var username = document.querySelector("#u");var password = document.querySelector("#p");function send() {// form-data数据提交使用FormData对象var data = new FormData();data.append("username",username.value);data.append("password",password.value);ajax({method: "POST",url:"request/form-data",// form-data不要设置contentType字段,发数据的时候ajax会自动生成body: data,callback: function(status,resp){alert("响应状态码:"+status+",响应正文:"+resp)}})}</script>
</body>
</html>

后端代码:

package org.example.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/request/form-data")
//要获取form-data格式的数据就必须加上这个注解
@MultipartConfig
public class requestFormData extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");System.out.printf("username=%s,password=%s\\n",username,password);}
}

2.5发送form-data格式的数据(文件上传)

(1)代码:
前端代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input id="u" type="text" placeholder="请输入账号"><br><input id="p" type="password" placeholder="请输入密码"><br><input id="f" type="file"><br><button onclick="send()">ajax form-data提交</button><script src="ajax.js"></script><script>var username = document.querySelector("#u");var password = document.querySelector("#p");var head = document.querySelector("#f");function send() {// form-data数据提交使用FormData对象var data = new FormData();data.append("username",username.value);data.append("password",password.value);var choosedFiles = head.files[0];if(choosedFiles){data.append("head",choosedFiles);}ajax({method: "POST",url:"request/form-data-file",// form-data不要设置contentType字段,发数据的时候ajax会自动生成body: data,callback: function(status,resp){alert("响应状态码:"+status+",响应正文:"+resp)}})}</script>
</body>
</html>

后端代码:

package org.example.servlet;import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;@WebServlet("/request/form-data-file")
//要获取form-data格式的数据就必须加上这个注解
@MultipartConfig
public class requestFormDataFile extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// form-data上传简单类型的数据通过getParameter获取String username = req.getParameter("username");String password = req.getParameter("password");// form-data上传文件通过getPath获取,返回值part对象就可以获取文件的相关信息,也可以对其进行操作Part head = req.getPart("head");String path = "E:/TMP/" + head.getSubmittedFileName();head.write(path);//保存客户端上传的文件到服务端本地System.out.println(head.getSubmittedFileName());//获取上传的文件名System.out.println(path);System.out.println(head.getSize());//获取上传文件的字节数System.out.printf("username=%s,password=%s\\n",username,password);}
}

抓包结果:
servlet(2)—javaEE
servlet(2)—javaEE

打印结果:
servlet(2)—javaEE
(2)保存的文件如何设计
①文件较小且上传文件的数据量不大,可以考虑使用数据库,将二进制数据转换为字符串(Base64),然后保存;文件较大,不考虑使用数据库保存,一般使用单独的服务器来做
②文件较大,放在服务器的本地硬盘上,但是注意不能放在项目的目录下,对于访问问题,可以自己写代码提供服务资源,请求数据包含一些信息就可以返回不同文件的响应

3.服务端返回响应

3.1返回HTML格式的数据(servlet返回动态网页)

(1)原因:HTML是静态的,不通过ajax是无法访问一个网页构造不同的内容
(2)servlet返回动态网页就是根据条件来拼接HTML字符串

package org.example.servlet;import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/response/html")
public class responseHtml extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {String userId = req.getParameter("userId");String html = "<P>欢迎你,%s</P>";String name = "张三";if(!"1".equals(userId)){name = "李四";}String body = String.format(html,name);resp.setContentType("text/html");resp.setCharacterEncoding("UTF-8");resp.getWriter().write(body);}
}

servlet(2)—javaEE
servlet(2)—javaEE

3.2返回JSON格式的数据

(1)序列化和反序列化

序列化:站在自己程序的角度,把自己程序中的对象转化为其他格式,用于返回响应数据
反序列化:站在自己程序的角度,把其他格式的数据转化为自己程序中的对象,用于接收请求数据

(2)测试json在Java中的使用
成员类:

package org.example.servlet;public class User {private String username;private String password;@Overridepublic String toString() {return "User{" +"username='" + username + '\\'' +", password='" + password + '\\'' +'}';}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;}
}

班级类:

package org.example.servlet;import java.util.List;public class classes {private int id;private String name;private List<User> student;@Overridepublic String toString() {return "classes{" +"id=" + id +", name='" + name + '\\'' +", student=" + student +'}';}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<User> getStudent() {return student;}public void setStudent(List<User> student) {this.student = student;}
}

测试JSON在java中的使用:

package org.example.servlet;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;public class textJSON {public static void main(String[] args) throws JsonProcessingException {// json反序列化:JSON字符串转java对象String json = "{\\"username\\":\\"in\\",\\"password\\":\\"123\\"}";// 需要使用Jackson框架提供的api来完成// 这个对象就是辅助完成JSON字符串和java对象相互转化ObjectMapper objectMapper = new ObjectMapper();// 可以转换为map,但是还是不但方便
//        HashMap map = objectMapper.readValue(json,HashMap.class);
//        System.out.println(map);//结果:{password=123, username=in}// 建议:自定义一个类型,成员变量名就是JSON字符串的键名,类型要保持一致User user = objectMapper.readValue(json,User.class);System.out.println(user);//结果:User{username='in', password='123'}//简单类型的JSON对象User user1 = new User();user1.setUsername("张三");user1.setPassword("123");String json1 = objectMapper.writeValueAsString(user1);//结果:{"username":"张三","password":"123"}System.out.println(json1);User user2 = new User();user2.setUsername("李四");user2.setPassword("456");//初始化list,包含user1和user2两个对象List<User> list = Arrays.asList(user1,user2);String json2 = objectMapper.writeValueAsString(list);//结果:[{"username":"张三","password":"123"},{"username":"李四","password":"456"}]System.out.println(json2);//复杂类型的JSON对象classes classes1 = new classes();classes1.setId(1);classes1.setName("hehe");classes1.setStudent(list);String json3 = objectMapper.writeValueAsString(classes1);System.out.println(json3);//结果:{"id":1,"name":"hehe","student":[{"username":"张三","password":"123"},{"username":"李四","password":"456"}]}}
}

(3)代码
前端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h4>班级信息</h3><p id="class_info"></p><ul></ul><script src="ajax.js"></script><script>var classInfo = document.querySelector("#class_info");var studentList = document.querySelector("ul");ajax({method: "GET",url: "response/json",callback:function(status,resp){console.log("响应状态码:"+status+",响应正文:"+resp);var json = JSON.parse(resp);console.log(json);// 解析响应的班级信息的数据classInfo.innerHTML = `班级id:${json.id},班级姓名:${json.name}`// 解析响应的学生列表的信息var content = '';for(var stu of json.student){content += `<li>学生姓名:${stu.username},账号密码:${stu.password}</li>`}studentList.innerHTML = content;}});</script>
</body>
</html>

ajax封装的代码:

// 参数 args 是一个 JS 对象, 里面包含了以下属性
// method: 请求方法
// url: 请求路径
// body: 请求的正文数据
// contentType: 请求正文的格式
// callback: 处理响应的回调函数, 有两个参数, 响应正文和响应的状态码
function ajax(args) {var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {// 0: 请求未初始化// 1: 服务器连接已建立// 2: 请求已接收// 3: 请求处理中// 4: 请求已完成,且响应已就绪if (xhr.readyState == 4) {args.callback(xhr.status, xhr.responseText)}}xhr.open(args.method, args.url);if (args.contentType) {xhr.setRequestHeader('Content-type', args.contentType);}if (args.body) {xhr.send(args.body);} else {xhr.send();}
}

后端代码:

package org.example.servlet;import com.fasterxml.jackson.databind.ObjectMapper;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;@WebServlet("/response/json")
public class responseJSON extends HttpServlet {private static final ObjectMapper m = new ObjectMapper();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {User user1 = new User();user1.setUsername("张三");user1.setPassword("123");User user2 = new User();user2.setUsername("李四");user2.setPassword("456");List<User> list = Arrays.asList(user1,user2);//复杂类型的JSON对象classes classes1 = new classes();classes1.setId(1);classes1.setName("hehe");classes1.setStudent(list);//返回给前端一个JSON字符串String json = m.writeValueAsString(classes1);//设置响应正文的数据格式resp.setContentType("application/json");//设置响应正文的编码resp.setCharacterEncoding("UTF-8");//设置到body中resp.getWriter().write(json);}
}

完成后端代码的结果
servlet(2)—javaEE
开发前端后的结果
servlet(2)—javaEE
(4)请求和响应
servlet(2)—javaEE

请求:前端如果是发送JSON:JSON.stringify(json对象);servlet(2)—javaEE
后端如果解析这个JSON:objectMapper.readValue(request.getInputStream, 类.class)servlet(2)—javaEE

响应:后端返回JSON字符串:response.writer(objectMapper.writerValueAsString(java对象);servlet(2)—javaEE
前端解析响应:ajax的callback回调函数,JSON.parse(方法参数中的响应正文字符串)servlet(2)—javaEE

4.实现请求一个路径,实现跳转或返回其他页面内容

4.1实现方式一:前端发ajax,后端返回json,前端解析响应,判断是否要跳转

前端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input id="u" type="text" placeholder="请输入账号"><br><input id="p" type="password" placeholder="请输入密码"><br><input type="button" value="模拟用户登录(前端跳转)" onclick="login()"><br><script src="ajax.js"></script><script>var username = document.querySelector("#u");var password = document.querySelector("#p");// 实现方式一:前端发ajax,后端返回json,前端解析响应,判断是否要跳转function login(){ajax({method: "POST",url: "jump",contentType: "application/x-www-form-urlencoded",body: "username="+username.value+"&password="+password.value,callback: function(status,resp){console.log("响应状态码:"+status+",响应正文:"+resp);//转换响应正文JSON字符串为JSON对象var json = JSON.parse(resp);if(json.ok){// 登录成功就跳转到这个路径location.href = "request-ajax.html";}else{// 不成功给出弹窗提示alert("账户或密码错误");}}})}</script>
</body>
</html>

后端代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><input id="u" type="text" placeholder="请输入账号"><br><input id="p" type="password" placeholder="请输入密码"><br><input type="button" value="模拟用户登录(前端跳转)" onclick="login()"><br><script src="ajax.js"></script><script>var username = document.querySelector("#u");var password = document.querySelector("#p");// 实现方式一:前端发ajax,后端返回json,前端解析响应,判断是否要跳转function login(){ajax({method: "POST",url: "jump",contentType: "application/x-www-form-urlencoded",body: "username="+username.value+"&password="+password.value,callback: function(status,resp){console.log("响应状态码:"+status+",响应正文:"+resp);//转换响应正文JSON字符串为JSON对象var json = JSON.parse(resp);if(json.ok){// 登录成功就跳转到这个路径location.href = "request-ajax.html";}else{// 不成功给出弹窗提示alert("账户或密码错误");}}})}</script>
</body>
</html>

servlet(2)—javaEE

servlet(2)—javaEE
servlet(2)—javaEE

4.2实现方式二:前端发ajax,后端登录成功直接跳转,登录失败还是跳转本页面

但是不建议返回HTML,这里就不详细介绍了(会出现重定向的问题)

5.总结

5.1请求和响应的前后端代码

servlet(2)—javaEE

5.2服务端获取数据的方式

servlet(2)—javaEE

5.3服务端返回数据的方式

servlet(2)—javaEE