Java EE 进阶:Spring MVC(2)
cookie和session的关系
两者都是在客户端和服务器中进行存储数据和传递信息的工具
cookie和session的区别
Cookie是客⼾端保存⽤⼾信息的⼀种机制.
Session是服务器端保存⽤⼾信息的⼀种机制.
Cookie和Session之间主要是通过SessionId关联起来的,SessionId是Cookie和Session之间的 桥梁。
Cookie和Session经常会在⼀起配合使⽤.但是不是必须配合,完全可以⽤Cookie来保存⼀些数据在客⼾端.这些数据不⼀定是⽤⼾⾝份信息,也不⼀定是 SessionId。
获取cookie
传统的获取cookie
HttpServletRequest , HttpServletResponse 是Servlet提供的两个类,是Spring MVC⽅法的内置对象.需要时直接在⽅法中添加声明即可
HttpServletRequest:对象代表客户端的请求当客户端通过Http协议访问服务端时,Http请求中的所有信息封装在这个对象中,通过这个对象提供的方法,可以获得客户端的所有信息
HttpServletResponse 对象代表服务器的响应.HTTP响应的信息都在这个对象中
//传统的获取cookie@RequestMapping("t13")public String t13(HttpServletRequest request, HttpServletResponse response){Cookie[] cookies = request.getCookies();if(cookies!=null){for (Cookie cookie:cookies) {System.out.println(cookie.getName()+":"+cookie.getValue());}}return "返回cookie成功";}
利用注释获取cookie的方式
//利用注解获取cookie@RequestMapping("t14")public String t14(@CookieValue("java") String java){return "获取cookie中的java成功"+ java;}
session的存储与获取
session的存储
//存储session@RequestMapping("/setSession")public String setSession(HttpServletRequest request){HttpSession session = request.getSession();session.setAttribute("username","zhangsan");session.setAttribute("age","17");return "设置session成功";}
session的获取
方法一:
//获取session,方法一@RequestMapping("/getSession1")public String getSession1(HttpServletRequest request){HttpSession session = request.getSession(/*true*/);if (session==null){return "获取失败";}else {String username =(String) session.getAttribute("username");// Integer age =(Integer) session.getAttribute("age");return "登录的用户为"+ username;}}
方法二:
//获取session,方法二@RequestMapping("/getSession2")public String getSession2(HttpSession session){//HttpSession session默认session中的值为true,所以可以省略session为0String username =(String) session.getAttribute("username");return "登录的用户为"+ username;}
方法三:
//获取session,方法三@RequestMapping("/getSession3")public String getSession3(@SessionAttribute("username") String username){return "登录的用户为"+ username;}
获取header
传统的获取header
@RequestMapping("/getHeader1")public String getHeader1(HttpServletRequest request){String UserAgent = request.getHeader("User-Agent");return "从header中获取User-Agent"+UserAgent;}
通过抓包,发现获取的user-agent正确
简洁的获取header
@RequestMapping("/getHeader2")public String getHeader2(@RequestHeader("User-Agent")String UserAgent){return "从header中获取User-Agent"+UserAgent;}
响应
返回静态的页面
在创建前端的页面时,注意路径
在resources包中
比如index.html前端代码
<!doctype html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>用户登录首页</title>
</head><body>登录人: <span id="loginUser"></span><script src="js/jquery-git.min.js"></script><script>$.ajax({url: "/user/getLoginUser",type: "get",success: function(userName){$("#loginUser").text(userName);}});</script>
</body></html>
后端的代码
public class ResponseController {@RequestMapping("/t1")public String returnPage(){return "/index.html";}
返回数据
@requestBody
@RequestMapping("/t2")@ResponseBodypublic String returnData(){return "返回需要的数据";}
返回html的代码片段
@ResponseBody@RequestMapping("/t3")public String returnHTML(){return "<h1>我是一级标题</h1>";}
返回JSON
@ResponseBody@RequestMapping(value = "/t5")public UseInfo returnJson(){UseInfo useInfo=new UseInfo("zhangsan",1,1);return useInfo;}
设置状态码
@ResponseBody@RequestMapping(value = "/t6")public UseInfo steStatus(HttpServletResponse response){response.setStatus(404);UseInfo useInfo=new UseInfo("zhangsan",1,1);return useInfo;}
用户的登录
前端代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>登录页面</title>
</head><body><h1>用户登录</h1>用户名:<input name="userName" type="text" id="userName"><br>密码:<input name="password" type="password" id="password"><br><input type="button" value="登录" onclick="login()"><script src="js/jquery-git.min.js"></script><script>function login() {$.ajax({type: "POST",url: "/user/login",data: {userName: $("#userName").val(), password: $("#password").val() },success: function(result) {if (result) {location.href = "index.html"; } else {alert("密码错误,请确认");}},error: function(xhr, status, error) {alert("请求失败,请稍后再试:" + error);}});}</script>
</body></html>
后端代码
package com.blame.spring.demo;import ch.qos.logback.core.util.StringUtil;
import jakarta.servlet.http.HttpSession;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public boolean login(String userName, String passWord, HttpSession session){if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(passWord)){return false;}if("admin".equals(userName) && "admin".equals(passWord)){session.setAttribute(userName,"userName");return true;}return false;}@RequestMapping("/getUserLogin")public String getUserLogin(String userName,HttpSession session){String attribute =(String) session.getAttribute("userName");return userName;}
}
接口的定义
登录界面的接口定义
$.ajax({type: "POST",url: "/user/login",data: {userName: $("#userName").val(), password: $("#password").val() },success: function(result) {if (result) {location.href = "index.html"; } else {alert("密码错误,请确认");}},error: function(xhr, status, error) {alert("请求失败,请稍后再试:" + error);}});
计算器的实现
前端的代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><form action="calc/sum" method="post"><h1>计算器</h1>数字1:<input name="num1" type="text"><br>数字2:<input name="num2" type="text"><br><input type="submit" value=" 点击相加 "></form>
</body></html>
后端代码
@RequestMapping("/calc")
@RestController
public class CalcController {@RequestMapping("/sum")public String sum(Integer num1,Integer num2){if(num1==null || num2==null){return "输入错误,请重新输入";}Integer sum=num1+num2;return "结果是"+ sum;}
}
留言板的实现
前端代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>留言板</title><style>.container {width: 350px;height: 300px;margin: 0 auto;/* border: 1px black solid; */text-align: center;}.grey {color: grey;}.container .row {width: 350px;height: 40px;display: flex;justify-content: space-between;align-items: center;}.container .row input {width: 260px;height: 30px;}#submit {width: 350px;height: 40px;background-color: orange;color: white;border: none;margin: 10px;border-radius: 5px;font-size: 20px;}</style>
</head><body><div class="container"><h1>留言板</h1><p class="grey">输入后点击提交, 会将信息显示下方空白处</p><div class="row"><span>谁:</span> <input type="text" name="" id="from"></div><div class="row"><span>对谁:</span> <input type="text" name="" id="to"></div><div class="row"><span>说什么:</span> <input type="text" name="" id="say"></div><input type="button" value="提交" id="submit" onclick="submit()"><!-- <div>A 对 B 说: hello</div> --></div><script src="js/jquery-git.min.js"></script><script>load();function load() {$.ajax({type: "get",url: "/message/getList",success: function (messages) {if (messages != null && messages.length > 0) {var finalHtml = "";for (var m of messages) {finalHtml += "<div>" + m.from + "对" + m.to + "说:" + m.message + "</div>";}$(".container").append(finalHtml);}}});}function submit(){//1. 获取留言的内容var from = $('#from').val();var to = $('#to').val();var say = $('#say').val();if (from== '' || to == '' || say == '') {return;}$.ajax({type:"post",url:"/message/publish",contentType:"application/json",data:JSON.stringify({from:from,to:to,message:say}),success:function(result){var jsonObj = JSON.parse(result);if(jsonObj.ok==1){//2. 构造节点var divE = "<div>"+from +"对" + to + "说:" + say+"</div>";//3. 把节点添加到页面上 $(".container").append(divE);//4. 清空输入框的值$('#from').val("");$('#to').val("");$('#say').val("");}else{alert("发布失败")}}});}</script>
</body></html>
后端代码
package com.blame.spring.demo;import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;@RequestMapping("/message")
@RestController
public class MessageController {List<MessageInfo> messageInfoList=new ArrayList<>();@PostMapping(value = "/publish",produces = "application/json")public String publish(@RequestBody MessageInfo messageInfo){if(!StringUtils.hasLength(messageInfo.getMessage())|| !StringUtils.hasLength(messageInfo.getFrom())|| !StringUtils.hasLength(messageInfo.getTo())){return "{\"ok\":0}";}messageInfoList.add(messageInfo);return "{\"ok\":1}";}@GetMapping("getList")public List<MessageInfo> getList(){return messageInfoList;}
}
接口的定义
lombok工具的介绍
Lombok是⼀个Java⼯具库,通过添加注解的⽅式,简化Java的开发
首先先引入其依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
@Data
public class MessageInfo {private String from;private String to;private String message;
}
@Data 注解会帮助我们⾃动⼀些⽅法,包含getter/setter,equals,toString等
如下图:上面是Java程序的运行原理,下面是Lombok的作用
我们就不需要自己写getter和setter方法还有toString方法
@Data=@Getter+@Setter+@ToString+@EqualsAndHashCode+@RequiredArgsConstructor + @NoArgsConstructor
图书管理系统的实现
首先先做好前端代码的引入
前端代码仅供参考,重点看后端的代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>添加图书</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/add.css"></head><body><div class="container"><div class="form-inline"><h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16"><pathd="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" /></svg><span>添加图书</span></h2></div><form id="addBook"><div class="form-group"><label for="bookName">图书名称:</label><input type="text" class="form-control" placeholder="请输入图书名称" id="bookName" name="bookName"></div><div class="form-group"><label for="bookAuthor">图书作者</label><input type="text" class="form-control" placeholder="请输入图书作者" id="bookAuthor" name="author" /></div><div class="form-group"><label for="bookStock">图书库存</label><input type="text" class="form-control" placeholder="请输入图书库存" id="bookStock" name="count"/></div><div class="form-group"><label for="bookPrice">图书定价:</label><input type="number" class="form-control" placeholder="请输入价格" id="bookPrice" name="price"></div><div class="form-group"><label for="bookPublisher">出版社</label><input type="text" id="bookPublisher" class="form-control" placeholder="请输入图书出版社" name="publish" /></div><div class="form-group"><label for="bookStatus">图书状态</label><select class="custom-select" id="bookStatus" name="status"><option value="1" selected>可借阅</option><option value="2">不可借阅</option></select></div><div class="form-group" style="text-align: right"><button type="button" class="btn btn-info btn-lg" onclick="add()">确定</button><button type="button" class="btn btn-secondary btn-lg" onclick="javascript:history.back()">返回</button></div></form></div><script type="text/javascript" src="js/jquery.min.js"></script><script>function add() {alert("添加成功");location.href = "book_list.html";}</script>
</body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>图书列表展示</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/list.css"><script type="text/javascript" src="js/jquery.min.js"></script><script type="text/javascript" src="js/bootstrap.min.js"></script><script src="js/jq-paginator.js"></script></head><body><div class="bookContainer"><h2>图书列表展示</h2><div class="navbar-justify-between"><div><button class="btn btn-outline-info" type="button" onclick="location.href='book_add.html'">添加图书</button><button class="btn btn-outline-info" type="button" onclick="batchDelete()">批量删除</button></div></div><table><thead><tr><td>选择</td><td class="width100">图书ID</td><td>书名</td><td>作者</td><td>数量</td><td>定价</td><td>出版社</td><td>状态</td><td class="width200">操作</td></tr></thead><tbody><tr><td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td><td>1</td><td>大秦帝国第一册</td><td>我是作者</td><td>23</td><td>33.00</td><td>北京出版社</td><td>可借阅</td><td><div class="op"><a href="book_update.html?bookId=1">修改</a><a href="javascript:void(0)" onclick="deleteBook(1)">删除</a></div></td></tr><tr><td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td><td>2</td><td>大秦帝国第二册</td><td>我是作者</td><td>23</td><td>33.00</td><td>北京出版社</td><td>可借阅</td><td><div class="op"><a href="book_update.html?bookId=2">修改</a><a href="javascript:void(0)" onclick="deleteBook(2)">删除</a></div></td></tr><tr><td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td><td>3</td><td>大秦帝国第三册</td><td>我是作者</td><td>23</td><td>33.00</td><td>北京出版社</td><td>可借阅</td><td><div class="op"><a href="book_update.html?bookId=3">修改</a><a href="javascript:void(0)" onclick="deleteBook(3)">删除</a></div></td></tr><tr><td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td><td>4</td><td>大秦帝国第四册</td><td>我是作者</td><td>23</td><td>33.00</td><td>北京出版社</td><td>可借阅</td><td><div class="op"><a href="book_update.html?bookId=4">修改</a><a href="javascript:void(0)" onclick="deleteBook(4)">删除</a></div></td></tr></tbody></table><div class="demo"><ul id="pageContainer" class="pagination justify-content-center"></ul></div><script>getBookList();function getBookList() {$.ajax({type: "get",url: "/book/getList",success: function(books){var finalHtml = "";for(var book of books){finalHtml += '<tr>';finalHtml += '<td><input type="checkbox" name="selectBook" value="'+book.bookId+'" id="selectBook" class="book-select"></td>';finalHtml += '<td>'+book.bookId+'</td>';finalHtml += '<td>'+book.bookName+'</td>';finalHtml += '<td>'+book.author+'</td>';finalHtml += '<td>'+book.num+'</td>';finalHtml += '<td>'+book.price+'</td>';finalHtml += '<td>'+book.publish+'</td>';finalHtml += '<td>'+book.statusCN+'</td>';finalHtml += '<td><div class="op">';finalHtml += '<a href="book_update.html?bookId='+book.bookId+'">修改</a>';finalHtml += '<a href="javascript:void(0)" onclick="deleteBook('+book.bookId+')">删除</a>';finalHtml += '</div></td></tr>';}$("tbody").html(finalHtml);}});}//翻页信息$("#pageContainer").jqPaginator({totalCounts: 100, //总记录数pageSize: 10, //每页的个数visiblePages: 5, //可视页数currentPage: 1, //当前页码first: '<li class="page-item"><a class="page-link">首页</a></li>',prev: '<li class="page-item"><a class="page-link" href="javascript:void(0);">上一页<\/a><\/li>',next: '<li class="page-item"><a class="page-link" href="javascript:void(0);">下一页<\/a><\/li>',last: '<li class="page-item"><a class="page-link" href="javascript:void(0);">最后一页<\/a><\/li>',page: '<li class="page-item"><a class="page-link" href="javascript:void(0);">{{page}}<\/a><\/li>',//页面初始化和页码点击时都会执行onPageChange: function (page, type) {console.log("第"+page+"页, 类型:"+type);}});function deleteBook(id) {var isDelete = confirm("确认删除?");if (isDelete) {//删除图书alert("删除成功");}}function batchDelete() {var isDelete = confirm("确认批量删除?");if (isDelete) {//获取复选框的idvar ids = [];$("input:checkbox[name='selectBook']:checked").each(function () {ids.push($(this).val());});console.log(ids);alert("批量删除成功");}}</script></div>
</body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>修改图书</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/add.css">
</head><body><div class="container"><div class="form-inline"><h2 style="text-align: left; margin-left: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="40"fill="#17a2b8" class="bi bi-book-half" viewBox="0 0 16 16"><pathd="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" /></svg><span>修改图书</span></h2></div><form id="updateBook"><input type="hidden" class="form-control" id="bookId" name="id"><div class="form-group"><label for="bookName">图书名称:</label><input type="text" class="form-control" id="bookName" name="bookName"></div><div class="form-group"><label for="bookAuthor">图书作者</label><input type="text" class="form-control" id="bookAuthor" name="author"/></div><div class="form-group"><label for="bookStock">图书库存</label><input type="text" class="form-control" id="bookStock" name="count"/></div><div class="form-group"><label for="bookPrice">图书定价:</label><input type="number" class="form-control" id="bookPrice" name="price"></div><div class="form-group"><label for="bookPublisher">出版社</label><input type="text" id="bookPublisher" class="form-control" name="publish"/></div><div class="form-group"><label for="bookStatus">图书状态</label><select class="custom-select" id="bookStatus" name="status"><option value="1" selected>可借阅</option><option value="2">不可借阅</option></select></div><div class="form-group" style="text-align: right"><button type="button" class="btn btn-info btn-lg" onclick="update()">确定</button><button type="button" class="btn btn-secondary btn-lg" onclick="javascript:history.back()">返回</button></div></form></div><script type="text/javascript" src="js/jquery.min.js"></script><script>function update() {alert("更新成功");location.href = "book_list.html"}</script>
</body></html>
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="css/bootstrap.min.css"><link rel="stylesheet" href="css/login.css"><script type="text/javascript" src="js/jquery.min.js"></script>
</head><body><div class="container-login"><div class="container-pic"><img src="pic/computer.png" width="350px"></div><div class="login-dialog"><h3>登陆</h3><div class="row"><span>用户名</span><input type="text" name="userName" id="userName" class="form-control"></div><div class="row"><span>密码</span><input type="password" name="password" id="password" class="form-control"></div><div class="row"><button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button></div></div></div><script src="js/jquery.min.js"></script><script>function login() {$.ajax({type:"POST",URL:"/user/login",data:{name: $("#userName").val(),password: $("#password").val()},success:function(result){if(result){//账号密码正确location.href = "book_list.html";}else {alert("账号或密码错误");}}});//location.href = "book_list.html";}</script>
</body></html>
后端代码:
首先我们创建图书类BookInfo
@Data
public class BookInfo {private Integer bookId;private String bookName;private String author;private Integer num;private BigDecimal price;private Integer status;private String publish;private String statusCN;}
创建UserController实现登录验证接口
@RequestMapping("/user")
@RestController
public class userController {@RequestMapping("/login")public boolean login(String name, String password, HttpSession session){if(!StringUtils.hasLength(name) || !StringUtils.hasLength(password)){return false;}if("admin".equals(name) && "admin".equals(password)){session.setAttribute("userName",name);return true;}return false;}
}
创建BookController,来调用bookService,再调用BookDao,来实现图书列表
@RequestMapping("/book")
@RestController
public class BookController {@Autowiredprivate BookService bookService;@RequestMapping("/getList")public List<BookInfo> getList(){return bookService.getList();}
@Service
public class bookService {//bookDao是数据库访问中的一个对象,现在我们对status这个对象进行修改@Autowiredprivate BookDao bookDao;public static List<BookInfo> getList(){List<BookInfo> bookInfos=new ArrayList<>();for (BookInfo bookInfo:bookInfos) {if(bookInfo.getStatus()==1){bookInfo.setStatusCN("可借阅");}else {bookInfo.setStatusCN("已借出");}}return bookInfos;}
}
@Repository
public class BookDao {public List<BookInfo> macData(){//创建一个储存图书List<BookInfo> bookInfos=new ArrayList<>();for (int i = 1; i <=15 ; i++) {//找图书BookInfo bookInfo=new BookInfo();bookInfo.setBookId(i);bookInfo.setBookName("图书名称"+i);bookInfo.setAuthor("图书作者"+i);bookInfo.setNum(new Random().nextInt(100));bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));bookInfo.setStatus(i%2==0?2:1);bookInfo.setPublish("出版社"+i);bookInfos.add(bookInfo);}return bookInfos;}
}
最后调用前端页面的代码
应用分层
三层架构
把整体架构分为表现层、业务逻辑层和数据层.这种分层 ⽅式也称之为"三层架构".
1.表现层:就是展⽰数据结果和接受⽤⼾指令的,是最靠近⽤⼾的⼀层;
2. 业务逻辑层:负责处理业务逻辑, ⾥⾯有复杂业务的具体实现;
3. 数据层: 负责存储和管理与应⽤程序相关的数据
这三个部分,在Spring中体现为:
应用分层的好处
1.降低层与层之间的依赖,使结构更加的明确,利于各层逻辑的复用
2.开发人员可以只关注某一层,极大地降低了开发成本和维护时间
3.更容易用新的实现替换原有的层次的实现
希望能对大家有所帮助!
相关文章:

Java EE 进阶:Spring MVC(2)
cookie和session的关系 两者都是在客户端和服务器中进行存储数据和传递信息的工具 cookie和session的区别 Cookie是客⼾端保存⽤⼾信息的⼀种机制. Session是服务器端保存⽤⼾信息的⼀种机制. Cookie和Session之间主要是通过SessionId关联起来的,SessionId是Co…...
ShardingSphere 和 Spring 的动态数据源切换机制的对比以及原理
ShardingSphere 与 Spring 动态数据源切换机制的对比及原理 一、核心定位对比 维度ShardingSphereSpring动态数据源(如 AbstractRoutingDataSource)定位分布式数据库中间件轻量级多数据源路由工具核心目标分库分表、读写分离、分布式事务多数据源动态切…...

基于Django的协同过滤算法养老新闻推荐系统的设计与实现
基于Django的协同过滤算法养老新闻推荐系统(可改成普通新闻推荐系统使用) 开发工具和实现技术 Pycharm,Python,Django框架,mysql8,navicat数据库管理工具,vue,spider爬虫࿰…...
AI视频生成工具清单(附网址与免费说明)
以下是一份详细的AI视频制作网站总结清单,包含免费/付费信息及核心功能说明: AI视频生成工具清单(附网址与免费说明) 1. Synthesia 网址:https://www.synthesia.io是否免费:免费试用(生成视频…...

JavaWeb学习——HTTP协议
HTTP 协议 什么是 HTTP 协议 HTTP(超文本传输协议,HyperText Transfer Protocol)是用于在客户端(如浏览器)和服务器之间传输超文本(如网页、图片、视频等)的应用层协议。它是现代互联网数据通…...
QP 问题(Quadratic Programming, 二次规划)
QP 问题(Quadratic Programming, 二次规划)是什么? QP(Quadratic Programming,二次规划)是一类优化问题,其中目标函数是二次型函数,约束条件可以是线性等式或不等式。 QP 问题是线…...

VSTO(C#)Excel开发2:Excel对象模型和基本操作
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...

MySQL索引数据结构
目录 1 索引常用的数据结构 1.1 二叉树 1.2 平衡二叉树 1.3 红黑树 1.3 Hash表 1.4 B树 1.4 B树 2 MySQL索引的数据结构 2.1 MyISAM存储引擎索引 2.2 InnoDB存储引擎索引 2.2.1 聚集索引 2.2.2 非聚集索引 2.2.3 联合索引数 2.2.4 hash索引 1 索引常用的数据结构 1.1 二叉树 二…...

C 语 言 --- 数 组 (1)
C 语 言 --- 数 组1 数 组定义一维数组语 法 格 式初始化完 全 初 始 化不 完 全 初 始 化省 略 数 组 大 小不 初 始 化使 用 memset 初 始 化 类 型访 问 元 素一 维 数 组 在 内 存 中 的 存 储 总结 💻作 者 简 介:曾 与 你 一 样 迷 茫,…...
[视频编码]rkmpp 实现硬件编码
mpi_enc_test的命令参数描述说明 命令参数的描述说明如下: 命令参数 描述说明 -i 输入的图像文件。 -o 输出的码流文件。 -w 图像宽度,单位为像素。 -h 图像高度,单位为像素。 -hstride 垂直方向相邻两行之间的距离,单…...

3D数字化:家居行业转型升级的关键驱动力
在科技日新月异的今天,家居行业正经历着一场前所未有的变革。从传统的线下实体店铺到线上电商平台的兴起,再到如今3D数字化营销的广泛应用,消费者的购物体验正在发生翻天覆地的变化。3D数字化营销不仅让购物变得更加智能和便捷,还…...
网安知识点
1.SQL注入漏洞产生的原因是? 前端传到后端的数据,没有经过任何处理,直接当作sql语句的一部分来执行 2.讲一下sql注入,写入webshell需要哪些前提条件 开启导入导出权限secure-file-priv 站点根目录位置/路径 mysql用户对站点根目…...

天津大学02-深度解读DeepSeek:部署、使用、安全【文末附下载链接】
大模型风险与不当用例——价值观错位 大模型与人类价值观、期望之间的不一致而导致的安全问题,包含:• 社会偏见(Social Bias)LLM在生成文本时强化对特定社会群体的刻板印象,例如将穆斯林与恐怖主义关联,或…...
【kubernetes】service
目录 1. 说明2. 原理2.1 服务注册2.2 服务发现2.3 负载均衡 3. Service的类型3.1 ClusterIP3.2 NodePort3.3 LoadBalancer3.4 ExternalName 4. 使用场景 1. 说明 1.kubernetes中的service主要用于提供网络服务,并实现微服务架构中的几个核心功能:全自动…...

Python卷积神经网络(CNN)来识别和计数不同类型的工业零件
以下三种类型工业零件为例,使用卷积神经网络(CNN)来识别和计数不同类型的工业零件。以下是Python实现步骤: 数据准备:收集并标注包含不同形状(如方形、圆形、扇形)的工业零件图像数据集。 模型…...
MoonSharp 文档二
目录 6.Sharing objects 我们先来简单谈谈类型描述符 先说类型描述 稍微复杂一点 调用静态成员 应该使用 “:” 还是 “.” 重载 ByRef 参数(C# 中的 ref/out) 索引器 userdata 上的运算符和元方法 扩展方法 事件 关于 InteropAccessMode 的…...
android 支持自定义布局、线程安全、避免内存泄漏的 Toast 工具类
支持自定义布局:可以灵活地显示自定义样式的 Toast。 线程安全:确保在主线程中显示 Toast,避免崩溃。 避免内存泄漏:使用 ApplicationContext 和取消机制,防止内存泄漏问题。 工具类:作为一个通用的工具…...

景联文科技:以精准数据标注赋能AI进化,构筑智能时代数据基石
在人工智能技术席卷全球的浪潮中,高质量数据已成为驱动AI模型进化的核心燃料。作为全球领先的AI数据服务解决方案提供商,景联文科技深耕数据标注领域多年,以技术为基、以专业为本,致力于为全球客户提供全场景、高精度、多模态的数…...

Mysql的卸载安装配置以及简单使用
MySQL其它问题已经更新在:MySQL完善配置---可视化-CSDN博客 一、卸载 ①控制面板卸载 ②C盘隐藏项目>ProgramData>mysql相关文件夹,还有Program file下的MySQL文件夹 ③开始菜单栏搜索>服务,找到MySQL相关服务删除,如果再…...
使用 ResponseBodyEmitter 实现异步响应式数据流处理
1. 概述 1.1 什么是 ResponseBodyEmitter ResponseBodyEmitter 是 Spring MVC 提供的一个接口,用于支持异步返回响应数据流。它允许在控制器方法中逐步发送数据给客户端,而无需一次性生成完整的响应。 1.2 使用场景 实时数据推送(如股票行情、聊天消息等)。大量数据分批…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...