Day69补 前后端分离思想

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完成即可,页面中需要动态呈现内容的部分,都是交给后台开发工程师做数据绑定和基于服务器进行渲染的(服务器端渲染)

局部刷新

目前市场上大部分项目都是前后端完全分离的项目,页面中需要动态绑定的数据是交给客户端完成渲染的

  1. 向服务器端发送AJAX请求
  2. 把从服务器端获取的数据解析处理,拼接成我们需要展示的HTML字符串
  3. 把拼接好的字符串替换页面中的某一部分内容(局部刷新),页面不需要整体重新加载,局部渲染即可

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、dto

5.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;}}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/53264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

业务安全治理

业务安全治理 1.账号安全撞库账户盗用 2.爬虫与反爬虫3.API网关防护4.钓鱼与反制钓鱼发现钓鱼处置 5.大数据风控风控介绍 1.账号安全 撞库 撞库分为垂直撞库和水平撞库两种&#xff0c;垂直撞库是对一个账号使用多个不同的密码进行尝试&#xff0c;可以理解为暴力破解&#x…

MVCC机制解析:提升数据库并发性能的关键

MVCC机制解析&#xff1a;提升数据库并发性能的关键 MVCC&#xff08;Multi-Version Concurrency Control&#xff09; 多版本并发控制 。 MVCC只在事务隔离级别为读已提交(Read Committed)和可重复读(Repeated Read)下生效。 MVCC是做什么用的 MVCC是为了处理 可重复读 和…

C# 实时流转换为m3u8

主要通过FFmpeg 执行命令进行转换 FFmpeg 下载地址 命令行 ffmpeg -i "rtsp://your_rtsp_stream_address" -codec: copy -start_number 0 -hls_time 10 -hls_list_size 12 -f hls "output.m3u8"start_number 设置播放列表中最先播放的索引号&#xff0c;…

形式向好、成本较低、可拓展性较高的名厨亮灶开源了

简介 AI视频监控平台, 是一款功能强大且简单易用的实时算法视频监控系统。愿景在最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;减少企业级应用约 95%的开发成本&#xff0c;在强大视频算法加…

C++_21_模板

模板 简介&#xff1a; 一种用于实现通用编程的机制。 通过使用模板我们可以编写可复用的代码&#xff0c;可以适用于多种数据类型。 C模板的语法使用角括号 < > 来表示泛型类型&#xff0c;并使用关键字 template 来定义和声明模板 概念&#xff1a; c范式编程 特点&…

海外大带宽服务器连接失败怎么办?

在全球化日益加深的今天&#xff0c;海外大带宽服务器已成为企业拓展国际市场、提升业务效率的重要工具。然而&#xff0c;面对复杂多变的网络环境和技术挑战&#xff0c;服务器连接失败的问题时有发生&#xff0c;这不仅影响了企业的正常运营&#xff0c;还可能带来经济损失和…

如何写一个自动化Linux脚本去进行等保测试--引言

#我的师兄喜欢给我的休闲实习生活加活&#xff0c;说是让我在实习期间写一个自动化脚本去进行等保测试。呵呵哒。 怎么办呢&#xff0c;师兄的指令得完成&#xff0c;师兄说让我使用Python完成任务。 设想如下&#xff1a; 1、将Linux指令嵌入到python脚本中 2、调试跑通 …

【简历】25届河南某一本JAVA简历:从头到尾都表现的不懂技术

注&#xff1a;为保证用户信息安全&#xff0c;姓名和学校等信息已经进行同层次变更&#xff0c;内容部分细节也进行了部分隐藏 简历总体说明 今天看一份河南某重点一本大学的Java简历。 校招备战第一法则&#xff1a;必须确定自己的求职层次&#xff0c;是大厂、中厂还是小…

php语言基本语法

HP&#xff08;Hypertext Preprocessor&#xff09;是一种广泛使用的开源服务器端脚本语言&#xff0c;特别适合于Web开发。 它能够嵌入到HTML中&#xff0c;执行动态网页内容。 PHP的一些基本语法元素&#xff1a; 1. 基本结构 PHP代码通常嵌入到HTML中&#xff0c;以<…

OpenHarmony(鸿蒙南向开发)——小型系统芯片移植指南(二)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量系统芯片移植指南(一) Op…

基于深度学习的图像分类或识别系统(含全套项目+PyQt5界面)

目录 一、项目界面 二、代码实现 1、数据集结构 2、设置需要模型的训练参数和指定数据集路径 3、网络代码 4、训练代码 5、评估代码 6、结果显示 三、项目代码 一、项目界面 二、代码实现 1、数据集结构 每一个文件夹对应一个类别的数据 2、设置需要模型的训练参数和…

09.20 C++对C的扩充以及C++中的封装、SeqList

SeqList.h #ifndef SEQLIST_H #define SEQLIST_H#include <iostream> #include<memory.h> #include<stdlib.h> #include<string.h>using namespace std;//typedef int datatype; //类型重命名 using datatype int;//封装一个顺序表 class Seq…

app抓包 chrome://inspect/#devices

一、前言&#xff1a; 1.首先不支持flutter框架&#xff0c;可支持ionic、taro 2.初次需要翻墙 3.app为debug包&#xff0c;非release 二、具体步骤 1.谷歌浏览器地址&#xff1a;chrome://inspect/#devices qq浏览器地址&#xff1a;qqbrowser://inspect/#devi…

新媒体运营

一、新媒体运营的概念 1.新媒体 2.新媒体运营的五大方向 用户运营 产品运营 。。。 二、新媒体的岗位职责及要求 三、新媒体平台

快速开发与维护:探索 AndroidAnnotations

在移动应用开发的世界中&#xff0c;效率和可维护性是两个至关重要的要素。随着应用功能的不断增长和用户需求的不断变化&#xff0c;开发者们一直在寻找能够提高生产力的工具和框架。今天&#xff0c;我们将深入探讨一个能够帮助开发者实现快速开发和易于维护的框架——Androi…

dgl库安装

此篇文章继续上一篇pytorch已经安装成功的情况 &#xff08;python3.9&#xff0c;pytorch2.2.2&#xff0c;cuda11.8&#xff09; 上一篇pytorch安装教学链接 选择与之匹配的版本 输入下方代码进行测试 import dgl.data dataset dgl.data.CoraGraphDataset() print(‘Numb…

使用宝塔部署项目在win上

项目部署 注意&#xff1a; 前后端部署项目&#xff0c;需要两个域名&#xff08;二级域名&#xff0c;就是主域名结尾的域名&#xff0c;需要在主域名下添加就可以了&#xff09;&#xff0c;前端一个&#xff0c;后端一个 思路&#xff1a;访问域名就会浏览器会加载前端的代…

【Redis入门到精通二】Redis核心数据类型(String,Hash)详解

目录 Redis数据类型 1.String类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 2.Hash类型 &#xff08;1&#xff09;常见命令 &#xff08;2&#xff09;内部编码 Redis数据类型 查阅Redis官方文档可知&#xff0c;Redis提供给用户的核心数据…

【HTML5】html5开篇基础(1)

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…

代码随想录冲冲冲 Day51 图论Part3

101. 孤岛的总面积 dfs 首先dfs的作用就是在遇到陆地的时候找到所有的周围陆地 对于这道题的dfs 会把所有的链接边缘的陆地变成海洋 这样在全部调整之后 剩下的就是孤岛了 这道题中的dfs的结束条件就是遇到海洋时 遇到每一个陆地就会把面积1&#xff0c;在每一次重新找到…