ajax前后端分离
前后端分离处理:前端------(数据)-----服务端----(数据)-----前端-----动态改变页面的内容
1.json
1、JSON:由于JSON易读以及纯文本格式的特性,可以非常容易地与其他程序进行沟通与数据交换。
2、JSON的数据结构通过大括号、中括号、逗号和冒号来组织数据,
冒号(键:值):
一个键值(key)对应一个值(value),字符串部分要用双引号来表示
“姓名”:“小陈” 、 “英文”:75 、 “数学”:80大括号(对象):
对象代表的是一系列“键:值”的集合,注意点:“键”一定要声明成字符串,也就是一定要加上“双引号”
{“姓名”:”小陈”,”英文”:75,”数学”:80}中括号(数组):
数组内可以存放数字、文字、布尔值、数组、对象等变量,无论是同时存放同一种性质的变量,以逗号隔开每个变量。
4、JSON字符串转换为JSON对象
var obj = eval(’(’ + str + ‘)’);或者:var obj = JSON.parseObject(str); (常用)5、JSON对象转JSON字符串
JSON.toJSONString(student)
2.AJAX
2.1 原生JS
Ajax(异步JavaScript和XML)
如果仔细观察一个Form表单的提交,你就会发现,一旦用户点击“Submit”按钮,表单开始提交,浏览器就会刷新页面,然后在新页面里告诉你操作是成功了还是失败了。如果不幸由于网络太慢或者其他原因,就会得到一个404页面。
这就是Web的运作原理:一次HTTP请求对应一个页面。
如果要让用户留在当前页面中,同时发出新的HTTP请求,就必须用JavaScript发送这个新请求,接收到数据后,再用JavaScript更新页面,这样一来,用户就感觉自己仍然停留在当前页面,但是数据却可以不断地更新
向服务器请求额外的数据而无须卸载页面(即刷新),会带来更好的用户体验
GET和POST
1.在Ajax使用的过程中,GET的使用频率要比POST高
2.GET 请求是最常见的请求类型,最常用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到URL的末尾,以便提交给服务器 (GET:通过URL地址栏中使用?后面的内容用&连接产生,显示出来)
通过 URL 后的问号给服务器传递键值对数据,服务器接收到返回响应数据。3.POST 请求可以包含非常多的数据,我们在使用表单提交的时候,很多就是使用的 POST 传输方式,而发送 POST 请求的数据,不会跟在 URL 的尾巴上,而是通过 send()方法向服务器提交数据。
xmlHttp.send("username=abc&password=123");
PS:从性能上来讲 POST 请求比 GET 请求消耗更多一些,用相同数据比较,GET 最多 比 POST 快两倍。
注意:async 异步 默认值是true
当使用同步时,可以不用侦听通信事件,直接在send后调用就可以,但是因为同步的原因如果一旦出现加载异常或者加载失败,将会报错,因此在ajax通信中尽量不要使用同步send():发送请求,如果该请求是异步模式(默认),该方法会立刻返回;相反,如果请求是同步模式,则直到请求的响应完全接受以后,该方法才会返回
注意: 所有相关的事件绑定必须在调用send()方法之前进行readystatechange事件
基于原生JS实现AJAX
<script>//1. 创建核心对象var xhttp;if (window.XMLHttpRequest) {xhttp = new XMLHttpRequest();} else {xhttp = new ActiveXObject("Microsoft.XMLHTTP");}//2. 获取响应(监听AJAX状态改变,获取响应信息)xhttp.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {alert(this.responseText);}};//3. 发送请求xhttp.open("GET", "http://localhost:8080/ajax-demo/ajaxServlet");//括号中传递的内容就是请求主体的内容xhttp.send();</script>
</body>
</html>
注意
全局刷新
在非完全前后端的项目中,前端开发只需要完成页面的制作,并且把一些基础的人机交互效果使用js完成即可,页面中需要动态呈现内容的部分,都是交给后台开发工程师做数据绑定和基于服务器进行渲染的(服务器端渲染)
局部刷新
目前市场上大部分项目都是前后端完全分离的项目,页面中需要动态绑定的数据是交给客户端完成渲染的
- 向服务器端发送AJAX请求
- 把从服务器端获取的数据解析处理,拼接成我们需要展示的HTML字符串
- 把拼接好的字符串替换页面中的某一部分内容(局部刷新),页面不需要整体重新加载,局部渲染即可
3.MVC
3.1 MVC
最典型的MVC就是JSP + servlet + javabean的模式
基本的概念:MVC = Model View Controller = 模型-视图-控制器
传统web开发在没有应用Ajax技术的时候,往往页面是用jsp,而这也让我们看到MVC的不足,视图与控制器间的过于紧密的连接,每次请求必须经过“控制器->模型->视图”这个流程,当java脚本 + 各种表达式 + html代码 +javascript代码混杂一块的时候,代码可读性十分差,而且给后面维护和修改代码的人带来很大阻碍
3.2 前后端分离
在传统的java web项目中,Jsp想做的事太多,既有后台数据的处理手法,也要承担视图展现的职能,Java代码、Html、CSS、Javascript、各种表达式、发送请求、接收数据、页面跳转…,让本该分工明确个的各单位糅杂在一起,给开发也带来了一些麻烦
使用Ajax,才真正有点分离的感觉,至少我们知道html、CSS、Js是属于前端版块,后台专注于业务逻辑和数据处理,让前台拿到结果,然后填充内容或者进行局部动态更新,渲染一下页面效果,前后端真正的交互在于这个json数据的请求和返回,而json的本质是 JS 对象的字符串表示法,以键值对呈现。后台有一个对象转化为json的过程,反过来,json传递到前端后,应该有一个内容解析的过程,要知道哪个键对应的值是代表什么含义,该怎么处理
前后端完全分离:
【优势】
1.我们可以根据需求,任意修改页面中的某一部分内容(例如实时刷新),整体页面不刷新,性能好,体验好(所有表单验证,需要实时刷新的需求都要基于AJAX实现)
2.有利于开发,提高开发效率
3.前后端的完全分离,后台不需要考虑前端如何实现,前端也不需要考虑后台用什么技术,真正意义上实现了技术的划分
4.可以同时进行开发:项目开发开始,首先制定前后端数据交互的接口文档(文档中包含了,调取哪个接口或者哪些数据等协议规范),后台把接口先写好,客户端按照接口调取即可,后台再去实现接口功能即可
【弊端】
1.不利于SEO( 搜索引擎优化 )优化:第一次从服务器端获取的内容不包含需要动态绑定的数据,所以页面的源代码中没有这些内容,不利于SEO收录,后期通过JS添加到页面中的内容,并不会写在页面的源代码中(是源代码不是页面结构)
2.交由客户端渲染,首先需要把页面呈现,然后在通过JS的异步AJAX请求获取数据,在进行数据绑定,浏览器再把动态增加的部分重新渲染,无形中浪费了一些时间,没有服务器端渲染页面呈现速度快
2.2 JQuery操作ajax
导入jQuery包
jQuery 对 AJAX 操作进行了封装,使用Jquery进行ajax操作的具体方法如下:
注意:表单是二进制liu数据还是纯文本数据
$(function(){ //请求参数 var list = {}; // $.ajax({ //请求方式 type : "POST", //请求的媒体类型 contentType: "application/json;charset=UTF-8", // contentType:json,//请求地址 url : "http://127.0.0.1/admin/list/", //"user?action=doLogin" //数据,发送给服务器的数据 data : $("#loginForm").serialize(), //是否异步async:true, //请求成功 success : function(data) { console.log(result); }, //请求失败,包含具体的错误信息 error : function(e){ console.log(e.status); console.log(e.responseText); } }); });
4.使用jQuery版本的Ajax实现学生管理系统MVC版本
下面以Spring MVC + Ajax + jsp示例(这里的ajax采用jQuery写法,原生js写法相较繁琐一点)
开发周期:2.5天
开发环境:IDEA、navicat
项目功能:
使用jQuery版本的Ajax实现学生管理系统MVC版本的所有功能
以组长牵头,带领组员实现业务1.开会讨论出业务的方案 – 业务文档
2.编写接口文档 – https://lbsyun.baidu.com/faq/api?title=webapi/guide/webservice-placeapi/polygon
3.数据库搭建
注意:2、3可同时执行
4.项目搭建 –
前端 – HTML、CSS、JS、jQuery(Ajax)、BootStrap
后端 – utils、pojo、dto5.mapper
6.service
7.controller
8.测试
相关业务如下:(省略版)
4.1 注册功能
注册功能因为有文件上传,属于二进制流数据,不能用传统方法解决
event.preventDefault();
是 JavaScript 中用于阻止默认事件行为的方法。
processData:处理数据(有上传文件时使用)
默认情况下,processData 的值是 true,以对象的形式上传的数据都会被转换为字符串的形式上传。而当上传文件的时候,则不需要把其转换为字符串,因此要改成false
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><h1>注册页面</h1>//这里添加了一个id属性<form id="registerForm" method="post" enctype="multipart/form-data">账号:<input type="text" name="username" id="username"/><span id="usernameInfo"></span><br/>密码:<input type="password" name="password"/><br/>姓名:<input type="text" name="name"/><br/>年龄:<input type="text" name="age"/><br/>性别:<input type="radio" name="sex" value="man" checked="checked"/>男<input type="radio" name="sex" value="woman"/>女<br/>爱好:<input type="checkbox" name="hobbies" value="football"/>足球<input type="checkbox" name="hobbies" value="basketball"/>篮球<input type="checkbox" name="hobbies" value="shop"/>购物<br/>上传头像:<input type="file" name="photo"/><br/>籍贯:<select id="province" name="province"><option value="xxx">-- 请选择 --</option></select>省<select id="city" name="city"><option value="xxx">-- 请选择 --</option></select>市<br/><input type="submit" value="注册"/><input type="button" value="返回" οnclick="goWelcome()"/></form><script src="js/jquery-1.8.2.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">function goWelcome() {window.location = "welcome.html";}$(function (){//给表单绑定一个提交事件$("#registerForm").submit(function (event){//阻止默认事件行为的发生event.preventDefault();//创建一个FormData对象let formData = new FormData(this);$.ajax({type:"post",url:"student?action=doRegister",processData:false,//不设置处理数据,因为使用了FormData对象contentType:false,//不设置内容类型,表单上设置了multipart/form-data//Ajax中的 data 属性就是 formdatadata:formData,async:true,success:function (data){if (data == "1"){alert("注册成功");}else if (data == "-1"){alert("注册失败");}}})})</script>
</body>
</html>
StudentController
//是否注册成功
public void doRegister(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {boolean register = studentService.register(request, response);String code;if(register){code = "1";}else{code = "-1";}response.getWriter().write(code);
}
运行结果:
4.2 登录功能
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head><title>Title</title>
</head>
<body><h1>登录页面</h1><!--action="user?action=doLogin" method="post" -->
<form id="loginForm">账号:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/> <!-- src="user?action=doDrawCode" -->验证码:<input type="text" name="userCode"/><img id="drawCode" width="120px" height="30px"><a href="#" id="reDrawCode">刷新</a><br/>记住我:<input type="checkbox" name="rememberMe"/><br/>角色:<select name="role"><option value="student">学生</option><option value="teacher">老师</option><option value="admin">管理员</option></select><br/><input id="loginBtn" type="button" value="登录"/><input type="button" value="返回" οnclick="goWelcome()"/>
</form><script src="js/jquery-1.8.2.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">function goWelcome() {window.location = "welcome.html";}img = document.getElementsByTagName("img")[0];$(function () {//登录功能$("#loginBtn").click(function () {$.ajax({type: "post",url: "user?action=doLogin",data: $("#loginForm").serialize(),//所有表单带name属性的都传给后端async: true,success: function (data) {if (data == "1") {window.location = "index.jsp";} else if (data == "-1") {alert("登录失败 -- 账号或密码错误");} else if (data == "-2") {alert("登录失败 -- 验证码错误");}}})})//验证码功能function showDrawCode() {$.ajax({type: "post",url: "user?action=doDrawCode",async: true,success: function () {//刷新验证码$("#drawCode").attr("src", "user?action=doDrawCode&" + new Date());}});}//页面加载时显示验证码showDrawCode();//点击验证码图片时刷新验证码$("#drawCode" ).click(function () {showDrawCode();})//点击刷新按钮时刷新验证码$("#reDrawCode" ).click(function () {showDrawCode();})})</script>
</body>
</html>
UserController
@WebServlet("/user")
public class UserController extends BaseServlet {private UserSevice userSevice = new UserServiceImpl();//绘制验证码功能public void doDrawCode(HttpServletRequest request, HttpServletResponse response) throws IOException {userSevice.drawCode(request,response);}//登录功能public void doLogin(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {//注意:表单传过来的数据,可以不做处理,userSevice.login也可以直接获取的到String login = userSevice.login(request, response);response.getWriter().write(login);}}
UserServiceImpl
public class UserServiceImpl implements UserSevice {private StudentMapper studentMapper = new StudentMapperImpl();private TeacherMapper teacherMapper = new TeacherMapperImpl();private AdminMapper adminMapper = new AdminMapperImpl();@Overridepublic void drawCode(HttpServletRequest request, HttpServletResponse response) throws IOException {//设置宽高的变量int width = 120;int height = 30;//创建画布BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//获取画笔Graphics graphics = image.getGraphics();//设置背景色 -- 填充矩形graphics.setColor(Color.BLUE);graphics.fillRect(0, 0, width, height);//设置验证码Random random = new Random();//随机函数String[] codes = {"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};Color[] colors = {Color.CYAN, Color.BLACK, Color.GREEN, Color.PINK, Color.WHITE, Color.RED, Color.ORANGE};StringBuffer sb = new StringBuffer();for (int i = 0; i < 4; i++) {String randomCode = codes[random.nextInt(codes.length)];//设置随机验证码Color randomColor = colors[random.nextInt(colors.length)];//设置随机颜色graphics.setColor(randomColor);//绘制随机颜色graphics.setFont(new Font("宋体", Font.BOLD, 20 + random.nextInt(10)));//设置字体(字体,样式,大小)graphics.drawString(randomCode, 20 + i * 25, 15 + random.nextInt(10));//设置单个验证码sb.append(randomCode);//拼接单个验证码,组成完整的验证码}//将系统验证码设置到Session对象中(会话对象)HttpSession session = request.getSession();//获取请求里的JSESSIONID(客户端Cookie里的数据),如果没有就创建Session对象,如果有就从Session容器中获取会话对象session.setAttribute("sysCode", sb.toString());//设置干扰线graphics.setColor(Color.YELLOW);for (int i = 0; i < 3; i++) {graphics.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height));//绘制直线(x1,y1,x2,y2)->两点为一线}//将画布以jpg形式的文件传出给客户端ImageIO.write(image, "jpg", response.getOutputStream());}@Overridepublic String login(HttpServletRequest request, HttpServletResponse response) {//获取请求中的数据//拿到的是前端data: $("#loginForm").serialize()String username = request.getParameter("username");String password = request.getParameter("password");String userCode = request.getParameter("userCode");String rememberMe = request.getParameter("rememberMe");String role = request.getParameter("role");//从Session对象中获取系统的验证码String sysCode = (String) request.getSession().getAttribute("sysCode");if (sysCode.equalsIgnoreCase(userCode)) {//验证码正确User user = null;if ("student".equals(role)) {user = studentMapper.getStudent(username, password);} else if ("teacher".equals(role)) {user = teacherMapper.getTeacher(username, password);} else if ("admin".equals(role)) {user = adminMapper.getAdmin(username, password);}if (user != null) {//登录成功//判断是否记住我if (rememberMe != null) {rememberMe(response, user.getUsername(), user.getName(), role, user.getPhoto());}//将数据存储到Session中HttpSession session = request.getSession();session.setAttribute("user", user);session.setAttribute("role", role);return "1";} else {//登录失败 -- 账号或密码错误return "-1";}} else {//登录失败 - 验证码错误return "-2";}}}
运行结果:
4.3 修改密码
index.jsp
直接跳转到jsp页面
<a href="resetPassword.jsp">修改密码</a>
resetPassword.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><!--action="user?action=doResetPassword" method="post" --><form id="resetPasswordForm"> //添加一个id<!--隐藏域,为了让修改页面拿到账号--><input type="hidden" name="username" id="username"/><input type="hidden" name="role" id="role" /><%-- ${username},账号是直接展示的 --%>账号:<span id="usernameInfo" ></span><br>原密码:<input type="password" name="password"/><br>新密码:<input type="password" name="newPassword"/><br>//改变提交按钮,设置一个id<input id="resetPasswordBtn" type="button" value="修改"/><input type="button" value="返回" οnclick="goIndex()"/></form><script src="js/jquery-1.8.2.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">function goIndex(){window.location = "index.jsp";}$(function (){//给提交按钮绑定一个点击事件$("#resetPasswordBtn").click(function(){$.ajax({url:"user?action=doResetPassword",type:"post",data:$("#resetPasswordForm").serialize(),dataType:"text",async:true,success:function(data){alert(data)if (data=="true"){alert("密码修改成功,请重新登录");window.location="login.jsp";}else if(data =="false"){alert("修改失败,原密码不正确");window.location="resetPassword.jsp";}}})})//为了表单有数据而设置的$.post("user",{"action":"getUser"},function(data){let user=eval("("+data+")").user;let role=eval("("+data+")").role;let username=user.username;//展示页面上的账号信息$("#usernameInfo").html(username);//给隐藏域赋值$("#username").val(username);$("#role").val(role);})})</script></body>
</html>
UserController
//修改密码功能public void doResetPassword(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {boolean resetPassword = userSevice.resetPassword(request, response);String username = request.getParameter("username");response.getWriter().write(String.valueOf(resetPassword));}//详情页面、修改密码页面得到数据public void getUser(HttpServletRequest request,HttpServletResponse response) throws IOException {User user = (User) request.getSession().getAttribute("user");String userJSONStr = JSON.toJSONString(user);String username = user.getUsername();String role = (String) request.getSession().getAttribute("role");String jsonStr = "{'role':'" + role + "','user':" + userJSONStr + "}";response.getWriter().write(jsonStr);}
UserServiceImpl
UserService接口省略
@Overridepublic boolean resetPassword(HttpServletRequest request, HttpServletResponse response) {//获取请求的数据String username = request.getParameter("username");String password = request.getParameter("password");String newPassword = request.getParameter("newPassword");String role = request.getParameter("role");System.out.println(username+"--"+password);System.out.println(role+"1");//声明一个User对象User user = null;//判断角色是否为studentif ("student".equals(role)) {System.out.println(role+"2");//根据用户名和密码查询学生表中的数据user = studentMapper.getStudent(username,password);System.out.println(user+"1");//判断角色是否为teacher} else if ("teacher".equals(role)) {//根据用户名和密码查询教师表中的数据user = teacherMapper.getTeacher(username, password);} else if ("admin".equals(role)) {//根据用户名和密码查询管理员表中的数据user = adminMapper.getAdmin(username, password);}//判断查询结果是否为空if (user != null) {//判断角色是否为studentif ("student".equals(role)) {//更新学生表中的密码studentMapper.update(username, newPassword);System.out.println(role+"3");return true;//判断角色是否为teacher} else if ("teacher".equals(role)) {//更新教师表中的密码teacherMapper.update(username, newPassword);return true;} else if ("admin".equals(role)) {//更新管理员表中的密码adminMapper.update(username, newPassword);return true;}} else {//设置修改失败的信息//request.setAttribute("msg","修改失败,原密码不正确");return false;}return false;}
4.4 查看所有学科
index.jsp
使用前后端分离,直接链接给一个jsp或者html就可以了
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head><title>Title</title>
</head>
<body><c:if test="${role eq 'admin'}"><a href="teacher?action=doGetTeachers&curPage=1">查看所有教师</a><a href="student?action=doGetStudents&curPage=1">查看所有学生</a><a href="courseList.jsp">查看所有学科</a></c:if></body>
</html>
courseList.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><button οnclick="goIndex()">返回</button>
<button οnclick="goAdd()">添加</button><h1>课程列表页面</h1><table border="1" width="600px" id="courseList"> //给表格设置一个id<tr><th>课程编号</th><th>课程名称</th><th>操作</th></tr></table><script src="js/jquery-1.8.2.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">function goIndex() {window.location = "index.jsp";}function goAdd() {window.location = "courseAdd.jsp";}$(function () {$.ajax({url: "course?action=doGetCourses",type: "post",dataType: "json",success: function (data) {//后端传回来的是JSON字符串(一个数组,直接遍历使用)var html = "";//遍历数据,进行拼接for (var i = 0; i < data.length; i++) {html += "<tr>" +"<td>" + data[i].id + "</td>" +"<td>" + data[i].name + "</td>" +"<td><a href='courseInfo.jsp?courseId=" + data[i].id + "'>修改</a> <a href='course?action=doDelete'>删除</a> </td>" +"</tr>";}//将数据写在表格中$("#courseList").html(html);}})})</script></body>
</html>
data:{id: 1, name: ‘xxx’},{id: 2, name: ‘Python’},{id: 3, name: ‘HTML’},{id: 13, name: ‘数学’}
CourseController
JSON.toJSONString
是将对象转化为Json字符串
@WebServlet("/course")
public class CourseController extends BaseServlet {private CourseService courseService = new CourseServiceImpl();public void doGetCourses(HttpServletRequest request, HttpServletResponse response) throws IOException {List<Course> courses = courseService.getCourses(request, response);//将对象转化为Json字符串 response.getWriter().write(JSON.toJSONString(courses));}}
CourseServiceImpl
返回一个List集合
public class CourseServiceImpl implements CourseService {private CourseMapper courseMapper = new CourseMapperImpl();@Overridepublic List<Course> getCourses(HttpServletRequest request, HttpServletResponse response) {List<Course> courses = courseMapper.getCourses();return courses;}}
运行结果:
4.5 老师功能
4.5.1 查看所有老师
详情页index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head><title>Title</title>
</head>
<body><c:if test="${role eq 'admin'}">
<%-- <a href="teacher?action=doGetTeachers&curPage=1">查看所有教师</a>--%><a href="teaList.jsp">查看所有教师</a><a href="student?action=doGetStudents&curPage=1">查看所有学生</a><a href="courseList.jsp">查看所有学科</a></c:if>
//...省略
</body>
</html>
教师列表页面 teaList.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><button οnclick="goIndex()">返回</button><button οnclick="goAdd()">添加</button><h1>教师列表页面</h1><table id="teaListTable" border="1" width="600px"> //添加一个id属性,方便插入数据<tr><th>账号</th><th>姓名</th><th>性别</th><th>年龄</th><th>省份</th><th>城市</th><th>课程</th><th>操作</th><th>操作</th></tr></table><script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">function goIndex() {window.location = "index.jsp";}function goAdd() {window.location = "teaAdd.jsp";}//拿到数据$(function () {$.ajax({url: "teacher?action=doGetTeachers",type: "get",dataType: "json",success: function (data) {createTable(data);},error: function (error) {console.log("Error: ", error);}})})//插入到表中function createTable(data) {let table = $("#teaListTable");for (let i = 0; i < data.length; i++) {let row = $("<tr></tr>");row.append($("<td></td>").text(data[i].teacher.username));row.append($("<td></td>").text(data[i].teacher.name));row.append($("<td></td>").text(data[i].teacher.sex));row.append($("<td></td>").text(data[i].teacher.age));row.append($("<td></td>").text(data[i].teacher.province));row.append($("<td></td>").text(data[i].teacher.city));row.append($("<td></td>").text(data[i].teacher.courseId));row.append($("<td></td>").html("<button class='delete-btn' data-username='" + data[i].teacher.username + "'>删除</button>"));row.append($("<td></td>").html("<button class='modify-btn' data-username='" + data[i].teacher.username + "'>修改</button>"));table.append(row);}}</script></body>
</html>
老师的控制器层 TeacherController
package com.zhj.controller;@WebServlet("/teacher")
public class TeacherController extends BaseServlet {private TeacherService teacherService = new TeacherServiceImpl();public void doGetTeachers(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {List<TeacherDto> teachersList = teacherService.getTeachersList(request, response);String teaJSONStr = JSON.toJSONString(teachersList);System.out.println(teaJSONStr);response.getWriter().write(teaJSONStr);}}
TeacherServiceImpl拿到老师的列表集合,TeacherService接口省略
package com.zhj.service.impl;public class TeacherServiceImpl implements TeacherService {@Overridepublic List<TeacherDto> getTeachersList(HttpServletRequest request, HttpServletResponse response) {//从数据库获取老师集合List<Teacher> teachers = teacherMapper.getTeachers(0,15);//处理教师集合List<TeacherDto> teacherDtos = DtoUtils.teacherDtoListHandler(teachers);return teacherDtos;}}
TeacherMapperImpl,如何从数据库中拿到老师集合
package com.zhj.mapper.impl;public class TeacherMapperImpl implements TeacherMapper {@Overridepublic List<Teacher> getTeachers(int offset, int count) {List<Teacher> teachers = null;try {teachers = DBUtils.commonQueryList(Teacher.class, "select * from teacher limit ?,?", offset, count);} catch (SQLException e) {throw new RuntimeException(e);}return teachers;}@Overridepublic String getProvince(String code) {String province = null;try {Connection connection = DBUtils.getConnection();String sql = "select name from provinces where code=?";PreparedStatement statement = connection.prepareStatement(sql);statement.setString(1,code);ResultSet resultSet = statement.executeQuery();if (resultSet.next()){province = resultSet.getString("name");}} catch (SQLException e) {throw new RuntimeException(e);}return province;}@Overridepublic String getCity(String code) {String city =null;try {Connection connection = DBUtils.getConnection();String sql = "select name from provinces where code=?";PreparedStatement statement = connection.prepareStatement(sql);statement.setString(1,code);ResultSet resultSet = statement.executeQuery();if (resultSet.next()){city = resultSet.getString("name");}} catch (SQLException e) {throw new RuntimeException(e);}return city;}
}
TeacherDto,处理列表中性别为man转成男,转成中文的
package com.zhj.dto;public class TeacherDto {private Teacher teacher;private String sex;private String province;private String city;//有参构造,无参构造,get,set,toString省略
}
工具类,省份城市太多了,省略不写
package com.zhj.utils;public class DtoUtils {public static TeacherDto teacherDtoHandler(Teacher teacher){//处理老师的性别数据String sex = teacher.getSex();if ("man".equals(sex)){sex = "男";}else if ("woman".equals(sex)){sex = "女";}TeacherMapper teacherMapper = new TeacherMapperImpl();String provinceCode = teacher.getProvince();String province = teacherMapper.getProvince(provinceCode);String cityCode = teacher.getCity();String city = teacherMapper.getCity(cityCode);TeacherDto teacherDto = new TeacherDto(teacher,sex,province,city);return teacherDto;}public static List<TeacherDto> teacherDtoListHandler(List<Teacher> teachers){List<TeacherDto> teacherDtos = new ArrayList<>();for (Teacher teacher : teachers) {TeacherDto teacherDto = teacherDtoHandler(teacher);teacherDtos.add(teacherDto);}return teacherDtos;}}
运行结果:
4.5.2 添加老师功能
teaList.jsp 点击添加按钮,跳转到添加页面
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><button οnclick="goIndex()">返回</button><button οnclick="goAdd()">添加</button><h1>教师列表页面</h1><table id="teaListTable" border="1" width="600px"> //添加一个id属性,方便插入数据<tr><th>账号</th><th>姓名</th><th>性别</th><th>年龄</th><th>省份</th><th>城市</th><th>课程</th><th>操作</th><th>操作</th></tr></table><script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">function goIndex() {window.location = "index.jsp";}function goAdd() {window.location = "teaAdd.jsp";}//...省略</script></body>
</html>
添加页面 teaAdd.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><h1>添加页面</h1><%--二进制数据--%><form id="addForm"> //添加一个id属性账号:<input type="text" name="username"/><br/>密码:<input type="password" name="password"/><br/>姓名:<input type="text" name="name"/><br/>年龄:<input type="text" name="age"/><br/>性别:<input type="radio" name="sex" value="man" checked="checked"/>男<input type="radio" name="sex" value="woman"/>女<br/>课程:<select><option value="1">JavaEE</option><option value="2">Python</option><option value="3">HTML</option></select><br/>上传头像:<input type="file" name="photo"/><br/>籍贯:<select id="province" name="province"><option value="xxx">-- 请选择 --</option></select>省<select id="city" name="city"><option value="xxx">-- 请选择 --</option></select>市<br/><input type="submit" value="添加"/><input type="button" value="返回" οnclick="goBack()"/></form><script src="js/jquery-1.8.2.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">function goBack(){window.location = "teacher?action=doGetTeachers&curPage=1";}$("#addForm").submit(function (event){event.preventDefault();let formData= new FormData(this);$.ajax({type:"post",url:"teacher?action=doAdd", //提交到后台的地址processData:false,contentType:false,data:formData,success:function (data){if (data == "1"){alert("添加成功");window.location = "teaList.jsp";}else {alert("添加失败");window.location="teaAdd.jsp";}}})})function showProvince(){$.get("province",{"action":"getProvinces"},function (data){let provinceArr = eval(data);for (let i = 0;i<provinceArr.length;i++){let code = provinceArr[i].code;let name = provinceArr[i].name;let option = $("<option></option>");$(option).val(code);$(option).text(name)$("#province").append(option)}})}showProvince();$("#province").change(function (){let v = $(this).val();if (v == "xxx"){$("#city").html("<option value='xxx'>-- 请选择 --</option>");}else{$.get("province",{"action":"getCities","code":v},function (data){//先清空城市列表$("#city").html("");//解析json数据let cityArr = eval(data);for (let i = 0;i<cityArr.length;i++){let code = cityArr[i].code;let name = cityArr[i].name;let option = $("<option></option>");$(option).val(code);$(option).html(name);$("#city").append(option);}})}})</script>
</body>
</html>
TeacherController
package com.zhj.controller;@WebServlet("/teacher")
public class TeacherController extends BaseServlet {private TeacherService teacherService = new TeacherServiceImpl();public void doAdd(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {boolean add = teacherService.add(request, response);String code;if (add) {code = "1";}else {code = "-1";}response.getWriter().write(code);}}
TeacherServiceImpl添加功能的具体实现,TeacherService接口省略
package com.zhj.service.impl;public class TeacherServiceImpl implements TeacherService {private TeacherMapper teacherMapper = new TeacherMapperImpl();private CourseService courseService = new CourseServiceImpl();@Overridepublic boolean isAdd(String username) {//获取请求的数据//从数据库中获取教师对象Teacher teacher = teacherMapper.getTeacher(username);if (teacher == null){return true;}return false;}@Overridepublic boolean add(HttpServletRequest request, HttpServletResponse response) {ParseRequestData<Teacher> parseRequestData = ParseRequestDataUtils.parseRequest(request, Teacher.class, "upload\\teacher");Teacher tea = parseRequestData.getT();InputStream in = parseRequestData.getIn();OutputStream out = parseRequestData.getOut();//判断账号是否已添加boolean add = isAdd(tea.getUsername());if (add){//将数据插入到教师表中teacherMapper.add(tea.getUsername(),tea.getPassword(),tea.getName(),tea.getSex(),tea.getAge(),tea.getCourseId(),tea.getProvince(),tea.getCity(),tea.getPhoto());//将头像存储到本地磁盘try {IOUtils.copy(in, out);in.close();out.close();} catch (IOException e) {throw new RuntimeException(e);}return true;}else {try {in.close();out.close();} catch (IOException e) {throw new RuntimeException(e);}request.setAttribute("msg","添加失败 -- 账号已被添加");return false;}}}
TeacherMapperImpl 从数据库添加一个老师,TeacherMapper接口省略
package com.zhj.mapper.impl;public class TeacherMapperImpl implements TeacherMapper {@Overridepublic void add(String username, String password, String name, String sex, int age, int courseId, String province,String city,String photo) {try {DBUtils.commonInsert("insert into teacher(username,password,name,sex,age,courseId,province,city,photo) values(?,?,?,?,?,?,?,?,?)",username,password,name,sex,age, courseId,province,city,photo);} catch (SQLException e) {throw new RuntimeException(e);}}}
运行结果:
4.5.3 修改老师
教师列表页面点击修改按钮
localStorage.setItem(‘username’, username):把数据存储在本地,另外一个页面可以取
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><h1>教师列表页面</h1><script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">// 修改学生信息$("#teaListTable").on("click", ".modify-btn", function () {let username = $(this).data("username");localStorage.setItem('username', username);// 处理响应window.location = "teaInfo.jsp";})function createTable(data) {let table = $("#teaListTable");for (let i = 0; i < data.length; i++) {let row = $("<tr></tr>");row.append($("<td></td>").text(data[i].teacher.username));row.append($("<td></td>").text(data[i].teacher.name));row.append($("<td></td>").text(data[i].teacher.sex));row.append($("<td></td>").text(data[i].teacher.age));row.append($("<td></td>").text(data[i].teacher.province));row.append($("<td></td>").text(data[i].teacher.city));row.append($("<td></td>").text(data[i].teacher.courseId));row.append($("<td></td>").html("<button class='delete-btn' data-username='" + data[i].teacher.username + "'>删除</button>"));row.append($("<td></td>").html("<button class='modify-btn' data-username='" + data[i].teacher.username + "'>修改</button>"));table.append(row);}}</script></body>
</html>
教师信息修改页面teaInfo.jsp
let username = localStorage.getItem(‘username’):老师列表页面传过来的本地数据,取出来
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head><title>Title</title>
</head>
<body><h1>教师信息修改页面</h1><form id="teaInfoForm"><!--隐藏域,用于传递教师账号--><input type="hidden" name="username" id="username"/><!--显示教师账号-->账号:<span id="usernameInfo"></span><br/><!--显示教师姓名,并允许修改-->姓名:<input type="text" name="name" /><br/><!--显示教师年龄,并允许修改-->年龄:<input type="text" name="age"/><br/><!--显示教师性别,并允许修改-->性别:<input type="radio" name="sex" value="man" }/>男<input type="radio" name="sex" value="woman" }/>女<br/><!--显示教师学科,并允许修改-->学科:<select name="course" id="course"></select><br/>上传头像:<input type="file" name="photo"/><span id="photoInfo"></span><br/>籍贯:<select id="province" name="province"><option value="xxx">-- 请选择 --</option></select>省<select id="city" name="city"><option value="xxx">-- 请选择 --</option></select>市<br><!--提交按钮,用于提交修改后的教师信息--><input type="submit" value="修改"/><!--返回按钮,用于返回首页--><input type="button" value="返回" οnclick="goIndex()"/></form><script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">let username = localStorage.getItem('username');$(function () {function showCourse() {$.get("course",{"action": "doGetCourses"},function (data) {let course = eval(data);for (let i = 0; i < course.length; i++) {let id = course[i].id;let name = course[i].name;let option = $("<option></option>");$(option).val(id);$(option).text(name);$("#course").append(option);}})}showCourse();//返回首页的函数function goIndex(){window.location = "index.jsp";}// 显示老师信息function showInfo() {$.post("teacher?action=doInitModify",{"username": username},function (data) {let teacher = eval("(" + data + ")");$("#usernameInfo").text(teacher.username);$("#username").val(teacher.username);$("input[name='name']").attr("placeholder", teacher.name);$("input[name='age']").attr("placeholder", teacher.age);teacher.sex === "man" ? $("input[value='man']").attr("checked", true) : $("input[value='woman']").attr("checked", true);// 显示学科let id = teacher.courseId;if ($("#course").val(id) == id) {$(this).attr("selected", true);}//头像$("#photoInfo").text(teacher.photo)//let code = teacher.province;if ($("#province".val(code)) == code) {$(this).attr("selected", true);}});}// 显示老师信息showInfo();function showProvince() {$.get("province",{"action": "getProvinces"},function (data) {let provinceArr = eval(data);for (let i = 0; i < provinceArr.length; i++) {let code = provinceArr[i].code;let name = provinceArr[i].name;let option = $("<option></option>");$(option).val(code);$(option).text(name)$("#province").append(option)}})}showProvince();$("#province").change(function () {let v = $(this).val();if (v == "xxx") {$("#city").html("<option value='xxx'>-- 请选择 --</option>");} else {$.get("province",{"action": "getCities", "code": v},function (data) {//先清空城市列表$("#city").html("");//解析json数据let cityArr = eval(data);for (let i = 0; i < cityArr.length; i++) {let code = cityArr[i].code;let name = cityArr[i].name;let option = $("<option></option>");$(option).val(code);$(option).html(name);$("#city").append(option);}})}})})// 提交表单$("#teaInfoForm").submit(function (event) {event.preventDefault(); // 阻止表单默认提交行为let formData = new FormData(this);// 序列化表单数据$.ajax({type: "POST",url: "teacher?action=doModify",processData: false,contentType: false,data: formData,async: true,success: function (data) {if (data == "1") {alert("修改成功");window.location = "teaList.jsp";} else if (data == "-1") {alert("修改失败");window.location = "teaInfo.jsp";}}});});</script>
</body>
</html>
CourseController先修改老师页面传递一个课程列表
package com.zhj.controller;@WebServlet("/course")
public class CourseController extends BaseServlet {private CourseService courseService = new CourseServiceImpl();public void doGetCourses(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {List<Course> courses = courseService.getCourses(request, response);String couJSONStr = JSON.toJSONString(courses);response.getWriter().write(couJSONStr);}}
CourseServiceImpl
@Overridepublic List<Course> getCourses(HttpServletRequest request, HttpServletResponse response) {List<Course> courses = courseMapper.getCourses();return courses;}
TeacherController
package com.zhj.controller;@WebServlet("/teacher")
public class TeacherController extends BaseServlet {private TeacherService teacherService = new TeacherServiceImpl();public void doInitModify(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {Teacher teacher = teacherService.initModify(request, response);String jsonStr = JSON.toJSONString(teacher);response.getWriter().write(jsonStr);}public void doModify(HttpServletRequest request, HttpServletResponse response) throws IOException {boolean modify = teacherService.modify(request, response);String code;if(modify){code = "1";}else{code = "-1";}response.getWriter().write(code);}}
TeacherServiceImpl
package com.zhj.service.impl;public class TeacherServiceImpl implements TeacherService {private TeacherMapper teacherMapper = new TeacherMapperImpl();private CourseService courseService = new CourseServiceImpl();@Overridepublic Teacher initModify(HttpServletRequest request, HttpServletResponse response) {//获取请求的数据String username = request.getParameter("username");//从数据库中获取教师对象Teacher teacher = teacherMapper.getTeacher(username);
// request.setAttribute("teacher", teacher);
// courseService.getCourses(request, response);return teacher;}@Overridepublic boolean modify(HttpServletRequest request, HttpServletResponse response) {ParseRequestData<Teacher> parseRequestData = ParseRequestDataUtils.parseRequest(request, Teacher.class, "upload\\teacher");Teacher tea = parseRequestData.getT();InputStream in = parseRequestData.getIn();OutputStream out = parseRequestData.getOut();Teacher tea1 = teacherMapper.getTeacher(tea.getUsername());//老数据try {if (tea.getPhoto() != null){//说明用户修改头像teacherMapper.update(tea.getUsername(),tea.getName(),tea.getSex(),tea.getAge(),tea.getCourseId(),tea.getProvince(),tea.getCity(),tea.getPhoto());IOUtils.copy(in,out);}else{teacherMapper.update(tea.getUsername(),tea.getName(),tea.getSex(),tea.getAge(),tea.getCourseId(),tea.getProvince(),tea.getCity());}if (in != null){in.close();}if (out != null){out.close();}} catch (IOException e) {throw new RuntimeException(e);}Teacher tea2 = teacherMapper.getTeacher(tea.getUsername());//修改后的数据String role = (String) request.getSession().getAttribute("role");if ("teacher".equals(role)){//更新Session里的数据request.getSession().setAttribute("name",tea.getName());//更新Cookie里的数据response.addCookie(CookieUtils.createCookie("name",tea.getName(),60*60*24*5));if (tea.getPhoto() != null){request.getSession().setAttribute("photo",tea.getPhoto());response.addCookie(CookieUtils.createCookie("photo",tea.getPhoto(),60*60*24*5));}}//判断是否修改成功if (tea1!=tea2){return true;}else {return false;}}}
TeacherMapperImpl
package com.zhj.mapper.impl;public class TeacherMapperImpl implements TeacherMapper {@Overridepublic void update(String username, String name, String sex, int age, int courseId,String province,String city) {try {DBUtils.commonUpdate("update teacher set name=?,sex=?,age=?,courseId=?,province=?,city=? where username=?",name,sex,age,courseId,province,city,username);} catch (SQLException e) {throw new RuntimeException(e);}}@Overridepublic void update(String username, String name, String sex, int age, int courseId, String province, String city, String photo) {try {DBUtils.commonUpdate("update teacher set name=?,sex=?,age=?,courseId=?,province=?,city=?,photo=? where username=?",name,sex,age,courseId,province,city,photo,username);} catch (SQLException e) {throw new RuntimeException(e);}}}
运行结果:
4.5.4 删除老师功能
teaList.jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><button οnclick="goIndex()">返回</button><button οnclick="goAdd()">添加</button><h1>教师列表页面</h1><table id="teaListTable" border="1" width="600px"><tr><th>账号</th><th>姓名</th><th>性别</th><th>年龄</th><th>省份</th><th>城市</th><th>课程</th><th>操作</th><th>操作</th></tr></table><script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript" charset="utf-8"></script><script type="text/javascript">// 删除学生信息$("#teaListTable").on("click", ".delete-btn", function () {let username = $(this).data("username");$.ajax({url: "teacher?action=doDelete",type: "POST",data: {username: username},success: function (data) {if (data == "1") {alert("删除成功");window.location = "teaList.jsp";} else if (data == "-1") {alert("删除失败");}}})})function createTable(data) {let table = $("#teaListTable");for (let i = 0; i < data.length; i++) {let row = $("<tr></tr>");row.append($("<td></td>").text(data[i].teacher.username));row.append($("<td></td>").text(data[i].teacher.name));row.append($("<td></td>").text(data[i].teacher.sex));row.append($("<td></td>").text(data[i].teacher.age));row.append($("<td></td>").text(data[i].teacher.province));row.append($("<td></td>").text(data[i].teacher.city));row.append($("<td></td>").text(data[i].teacher.courseId));row.append($("<td></td>").html("<button class='delete-btn' data-username='" + data[i].teacher.username + "'>删除</button>"));row.append($("<td></td>").html("<button class='modify-btn' data-username='" + data[i].teacher.username + "'>修改</button>"));table.append(row);}}</script></body>
</html>
TeacherController
package com.zhj.controller;@WebServlet("/teacher")
public class TeacherController extends BaseServlet {private TeacherService teacherService = new TeacherServiceImpl();public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {boolean delete = teacherService.delete(request, response);String code;if(delete){code = "1";}else{code = "-1";}response.getWriter().write(code);}}
TeacherServiceImpl
package com.zhj.service.impl;public class TeacherServiceImpl implements TeacherService {private TeacherMapper teacherMapper = new TeacherMapperImpl();private CourseService courseService = new CourseServiceImpl();@Overridepublic boolean delete(HttpServletRequest request, HttpServletResponse response) {String username = request.getParameter("username");teacherMapper.delete(username);Teacher teacher = teacherMapper.getTeacher(username);if (teacher == null){return true;}return false;}
}
TeacherMapperImpl
package com.zhj.mapper.impl;public class TeacherMapperImpl implements TeacherMapper {@Overridepublic void delete(String username) {try {DBUtils.commonUpdate("delete from teacher where username = ?",username);} catch (SQLException e) {throw new RuntimeException(e);}}@Overridepublic Teacher getTeacher(String username) {Teacher teacher = null;try {teacher = DBUtils.commonQueryObj(Teacher.class, "select * from teacher where username = ?", username);} catch (SQLException e) {throw new RuntimeException(e);}return teacher;}}
运行结果: