SpringMVC:Ajax、拦截器、文件上传、文件下载

文章目录

  • SpringMVC - 06
  • 一、Ajax
    • 1. 概述
    • 2. Ajax 异步加载数据
      • 1. 单个数据
      • 2. 对象
    • 3. 实践
    • 4. 总结
  • 二、拦截器
    • 1. 概述
    • 2. 实现
    • 3. 实践
    • 4. 总结
  • 三、文件上传:Upload
    • 1. 准备工作
    • 2. 步骤
    • 3. 效果
  • 四、文件下载:Download
    • 1. 步骤
    • 2. 效果
    • 3. 总结
  • 注意:

SpringMVC - 06

一、Ajax

1. 概述

AjaxAsynchronous Javascript And XML(异步 JavaScript 和 XML)

  1. 使用 Ajax 技术,网页能够快速地将增量更新呈现在用户界面上,而不需要刷新整个页面,这使得程序能够更快地回应用户的操作;

  2. Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的 Web 应用程序的技术

  3. 使用 Ajax 的最大优点,就是能在不更新整个页面的前提下维护数据,即在不需要刷新页面的情况下,就可以产生局部刷新的效果。

需要用到 jQuery 实现 Ajax,它是一个快速、简洁的 JavaScript 框架,具有 js 的大量函数,引入 jQuery 的方法

  1. 进入 jQuery 官网:点此进入,找到 [Download the uncompressed, development jQuery 3.7.0]
  2. 点击链接,出现 js 代码,通过 Ctrl + S 保存到下载的位置;
  3. 在 web 文件夹新建 static 文件夹,将下载好的 jQuery 框架导入。

2. Ajax 异步加载数据

使用格式

<%-- 引入 jQuery 框架 --%>
<script src="${pageContext.request.contextPath}/static/jquery-3.7.0.js"></script><script>function xxx() {$.post({url:"${pageContext.request.contextPath}/请求地址",data:{"后端参数名":$("#前端参数名").val()},success:function (data) {成功之后执行的回调函数;}, error:function (data) {失败之后执行的回调函数;}})}
</script>

注意

  • script 标签必须成对,并且放在 body 的最后
  • $.post() 相当于 jQuery.post() ,使用时一定要提前引入 jQuery 框架;
  • $.post放在函数内,其中的参数有:
    • url请求地址
    • data :前端要发送给后端的数据,没有数据时可以省略
    • success成功之后执行的回调函数注意这里回调函数中参数 data 与上面的 data 不是同一个,这里是指后端传递给前端的数据;
    • error失败之后执行的回调函数
  • 之前是由后端控制转发或重定向,完成视图的跳转,而现在是由前端 Ajax 来控制,后端只需要提供数据(JSON 字符串)即可,Ajax 把主动权交给前端。

1. 单个数据

举例:当用户输入一个信息后,进行弹窗提示。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>测试</title><script src="${pageContext.request.contextPath}/static/jquery-3.7.0.js"></script><script>function a() {$.post({url:"${pageContext.request.contextPath}/mon/a1",data:{"name":$("#username").val()},success:function (data) {alert(data);}})}</script>
</head>
<body>
<h1><%-- 失去焦点时,发起一个请求(携带信息)到后台 --%>用户名:<input type="text" id="username" οnblur="a()">
</h1>
</body>
</html>

注意

  1. 前端向后端传递单个数据时,data 必须是键值对(JSON 字符串)的形式,这里的 name后端的参数名username前端的参数名
  2. 在 Ajax 中,前端参数的值(例如用户输入的信息)可以通过 $("#前端参数名").val() 的方式取到;
  3. console.log 可以在控制台输出信息
  4. alert 代表弹窗
  5. onblur 代表失去焦点时,执行函数;
  6. 该代码可以执行的操作是:在前端页面中,用户输入用户名信息,失去焦点时,执行函数 a() ,发起 /mon/a1 请求并携带前端数据给后端,后端执行成功(success)后,执行回调函数,此时回调函数的参数 data 为后端返回的数据,进行 alert 弹窗。

后端控制层代码

// 控制层中所有返回的字符串都不会经过视图解析器,而是直接返回字符串
@RestController
@RequestMapping("/mon")
public class AjaxController {@RequestMapping("/a1")public String a1(String name) {System.out.println(name);if ("Sun3285".equals(name)) {return "true";} else {return "false";}}
}

执行

2. 对象

举例:当用户点击【加载数据】按钮时,加载后台中的数据。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>测试</title><script src="${pageContext.request.contextPath}/static/jquery-3.7.0.js"></script><script>$(function () {$("#btn").click(function () {$.post({url:"${pageContext.request.contextPath}/mon/a2",success:function(data) {console.log(data);var obj = JSON.parse(data);console.log(obj);var html = "";for (let i = 0; i < obj.length; i++) {html += "<tr>" +"<td>" + obj[i].id + "</td>" +"<td>" + obj[i].name + "</td>" +"<td>" + obj[i].sex + "</td>" ++ "</tr>";}$("#content").html(html);}})})})</script>
</head>
<body>
<input type="button" value="加载数据" id="btn">
<table><tr><td>编号</td><td>姓名</td><td>性别</td></tr><tbody id="content"><%-- 后台数据 --%></tbody>
</table>
</body>
</html>

注意

  1. 重点看 Ajax 部分,因为前端不给后端传递数据,因此省略了 data;
  2. 后端传递给前端的数据 data 为 JSON 字符串,因此要先通过 JSON.parse(data) 解析为 JavaScript 对象,可以通过 console.log 来看到解析前后的结果;
  3. 该代码可以执行的操作是:在前端页面中,用户点击【加载数据】按钮时,通过 $("#btn").click 可以捕捉到,然后执行函数,发起 /mon/a2 请求给后端,后端执行成功(success)后,执行回调函数,此时回调函数的参数 data 为后端返回的数据,即一个 JSON 字符串,经过前端处理后,在页面中显示信息。

后端控制层代码

@RestController
@RequestMapping("/mon")
public class AjaxController {@RequestMapping("/a2")public String a2() throws JsonProcessingException {ArrayList<Student> studentList = new ArrayList<Student>();Student s1 = new Student(1, "Sun1234", "男");Student s2 = new Student(2, "Sun3285", "男");Student s3 = new Student(3, "Sun4399", "女");Collections.addAll(studentList, s1, s2, s3);// 后端传递给前端的是一个 JSON 字符串return new ObjectMapper().writeValueAsString(studentList);}
}

执行

3. 实践

需求:输入用户名和密码时,动态显示输入信息是否正确。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录</title><script src="${pageContext.request.contextPath}/static/jquery-3.7.0.js"></script><script>function login1() {$.post({url:"${pageContext.request.contextPath}/mon/login1",data:{"username":$("#username").val()},success:function (data) {console.log(data);if (data === "OK") {$("#usernameInfo").css("color", "green");} else {$("#usernameInfo").css("color", "red");}$("#usernameInfo").html(data);}})}function login2() {$.post({url:"${pageContext.request.contextPath}/mon/login2",data:{"username":$("#username").val(), "password":$("#password").val()},success:function (data) {console.log(data);if (data === "OK") {$("#passwordInfo").css("color", "green");} else {$("#passwordInfo").css("color", "red");}$("#passwordInfo").html(data);}})}</script>
</head>
<body>
<p>用户名:<input type="text" id="username" οnblur="login1()"><span id="usernameInfo"></span><br>密  码:<input type="text" id="password" οnblur="login2()"><span id="passwordInfo"></span>
</p>
</body>
</html>

后端控制层代码

@RestController
@RequestMapping("/mon")
public class AjaxController {@RequestMapping("/login1")public String login1(String username) {if ("Sun3285".equals(username)) {return "OK";} else {return "用户名输入有误";}}@RequestMapping("/login2")public String login2(String username, String password) {String result = login1(username);if ("OK".equals(result)) {if ("123456".equals(password)) {return "OK";} else {return "密码输入有误";}} else {return result;}}
}

注意:判断密码是否正确的前提是:先要判断用户名是否正确。

执行

4. 总结

  1. js 中三个等号为严格等于,指数据类型都要相等;
  2. 之前是由后端控制转发或重定向,完成视图的跳转,而现在是由前端 Ajax 来控制,后端只需要提供数据(JSON 字符串)即可,Ajax 把主动权交给前端;
  3. 前后端之间交互数据是以 JSON 字符串的形式;
  4. 标签中 id 和 name 的区别
    • id 一般用于 css 和 js 中引用,name 用于表单提交只有加了 name 属性的标签元素才会提交到服务器;
    • id 是唯一的标识符,不允许有重复值,可以通过它的值来获得对应的 html 标签对象,相当于人的身份证具有唯一性;
    • name 是控件的名字,当需要把控件所关联的数据传递到数据库时,就必须要设置 name 属性,相当于人的姓名,可以重名,用 value 可以设置控件的默认值。

二、拦截器

1. 概述

拦截器AOP 思想的具体应用,拦截器拦截的是请求,不拦截静态资源。

功能:用于对 SpringMVC 处理器进行预处理和后处理,可以自己定义一些拦截器来实现特定的功能。

过滤器和拦截器的区别

  • 过滤器

    1. 是 servlet 规范中的一部分,任何 JavaWeb 工程中都可以使用;
    2. 在 url-pattern 中配置了 /* 之后,可以对所有要访问的资源进行过滤;
    3. web.xml 中进行配置。
  • 拦截器

    1. 拦截器是 SpringMVC 框架的,只有使用了 SpringMVC 框架的工程才能使用;
    2. 拦截器只会拦截访问的控制器方法(控制类中的方法),如果访问的是 jsp/html/css/image/js 是不会进行拦截的;
    3. 在 Spring 配置文件中进行配置(因为拦截器是 SpringMVC 框架独有的)。

2. 实现

实现拦截器的步骤

  1. 自定义一个拦截器,实现 HandlerInterceptor 接口,重写方法;
  2. 在 Spring 配置文件中,配置拦截器,包括使用的拦截器以及要拦截的请求。
// 第一步:自定义一个拦截器 MyInterceptor,实现 HandlerInterceptor 接口,重写方法
public class MyInterceptor implements HandlerInterceptor {// 处理前public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return false;}// 处理后public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}// 清理public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

注意:preHandle 方法中,返回值为 true,表示执行下一个拦截器(放行),返回值为 false,表示不执行下一个拦截器(拦截)。

<!-- 第二步:在 Spring 配置文件中,对拦截器进行配置 -->
<mvc:interceptors><mvc:interceptor><!-- /** 表示所有请求都会经过拦截器 --><mvc:mapping path="/**"/><!-- 指定使用的拦截器 --><bean class="com.Sun3285.config.MyInterceptor"/></mvc:interceptor>
</mvc:interceptors>

3. 实践

需求:登录判断验证,如果进行了登录操作,并且用户名和密码正确,才可以进入首页,否则不能直接进入首页。

拦截前:可以进入登录界面进行登录操作,输入正确的用户名和密码,进入主界面,也可以在首页上直接点击超链接,进入主界面。

点击【主页面】时使用拦截器拦截,拦截的依据是:是否在 Session 中存放了指定的信息,因为只有登录成功,才会在 Session 中存放指定信息 usernameID。

第一步:自定义拦截器,如果 Session 中存放了指定的信息(进行了登录操作),就放行,否则,跳转到登录页面。

public class LoginInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();if (session.getAttribute("usernameID") != null) {return true;}request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);return false;}
}

第二步:在 Spring 配置文件中,配置拦截器,在首页点击【主页面】超链接时,进行拦截。

<!-- 拦截器配置 -->
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/toMain"/><bean class="com.Sun3285.config.LoginInterceptor"/></mvc:interceptor>
</mvc:interceptors>

运行结果

  • 没有进行登录操作,直接在首页点击【主页面】时,拦截器拦截,并跳转到登录页面。

  • 进行了登录,再在首页点击【主页面】时,可以直接跳转到主页面,因为此时 Session 中存放了指定的信息,拦截器放行

  • 此时关闭浏览器,重新打开,再在首页点击【主页面】时,拦截器拦截,并跳转到登录页面,因为此时拦截器得到的 session 为新的 session,其中没有存放指定的信息 usernameID。

4. 总结

  1. 在 WEB-INF 下的所有页面或者资源,只能通过 controller 或 servlet 进行访问;
  2. 请求转发可以访问 WEB-INF 下的所有页面或者资源,重定向不可以
  3. 可以在控制类的方法参数中直接拿到一些对象,如:HttpSession session、HttpServletRequest request、HttpServletResponse response 等,然后在方法内进行进一步操作。

三、文件上传:Upload

1. 准备工作

如果想使用 Spring 的文件上传功能,需要在上下文中配置 MultipartResolver。

为了能够上传文件,前端表单要求

  1. 必须将表单的 method 设置为 POST;
  2. 将 enctype 设置为 multipart/form-data,这样,浏览器才会把用户选择的文件以二进制数据发送给服务器。

后端要求

  1. 导入依赖:commons-fileupload
<!-- 文件上传 -->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version>
</dependency>

2. 步骤

文件上传的步骤

  1. 导入依赖;
  2. 编写前端页面:建立表单;
  3. 编写控制类,实现文件上传;
  4. 在 Spring 配置文件中配置文件上传。
  • 前端页面

  • 控制类

@Controller
public class FileController {// @RequestParam("file") 将 name="file" 控件得到的文件封装为 CommonsMultipartFile 对象@RequestMapping("/upload")public String uplode(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request) throws IOException {// 获取文件名String uploadFilename = file.getOriginalFilename();// 上传路径保存设置String path = request.getServletContext().getRealPath("/upload");File realPath = new File(path);if (!realPath.exists()) {realPath.mkdir();// realPath.mkdirs();}// 输出上传文件地址System.out.println("上传文件保存地址:" + realPath);// 通过 CommonsMultipartFile 的方法直接写文件file.transferTo(new File(realPath + "/" + uploadFilename));return "redirect:/index.jsp";}
}

注意:这部分代码可以直接使用只需要按需求改一下上传路径 path 即可,其中 upload 为新创建的文件夹,存放上传的文件。这里也可以把上传路径 path 直接用一个字符串表示。

  • 配置文件上传
<!-- 在 Spring 配置文件中配置文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 请求的编码格式 --><property name="defaultEncoding" value="utf-8"/><!-- 上传文件大小上限,可以省略,单位为字节(1MB=1048576字节) --><property name="maxUploadSize" value="10485760"/>
</bean>

3. 效果

文件上传后,控制台输出上传文件的地址,并且可以找到已上传的文件


四、文件下载:Download

1. 步骤

固定代码

@Controller
public class FileController {@RequestMapping("/download")public String download(HttpServletRequest request,HttpServletResponse response) throws IOException {// 要下载的文件地址和文件名String path = request.getServletContext().getRealPath("/files");String fileName = "导入的依赖总结.txt";File file = new File(path, fileName);// 设置 response 响应头response.reset();   // 设置页面不缓存,清空 bufferresponse.setCharacterEncoding("utf-8");  // 字符编码response.setContentType("multipart/form-data");  // 二进制传输数据// 设置下载文件response.setHeader("Content-Disposition","attachment;fileName=" + URLEncoder.encode(fileName, "utf-8"));// 读取文件:输入流InputStream is = new FileInputStream(file);InputStream bis = new BufferedInputStream(is);// 写出文件:输出流OutputStream os = response.getOutputStream();OutputStream bos = new BufferedOutputStream(os);// 下载操作(读取、写出)byte[] buffer = new byte[1024];int len = 0;while ((len = bis.read(buffer)) != 0) {bos.write(buffer, 0, len);bos.flush();}// 关闭资源bos.close();bis.close();return null;}
}

注意

  1. 这部分代码可以直接使用只需要按需求改一下要下载的文件地址和文件名,其中
    • 被下载文件的地址:这里是放在了 web 文件夹下的 files 文件夹中,最后会在生成的 out 文件夹下的子项目中;
    • 文件名:被下载的文件名。
  2. 记得最后要关闭资源,后开先关

2. 效果

无法下载文件,后端代码执行成功

判断应该是浏览器阻止了下载,更换浏览器再次尝试,可以下载成功

3. 总结

  • 上传路径 path 和被下载的文件地址 path 也都可以直接用一个字符串表示:
    • 上传路径 path 一般通过 request.getServletContext().getRealPath("/upload") 来将文件上传到服务器生成的 out 目录下的子项目中的 upload 包(如果没有 upload 包,会自动新建)中;
    • 下载时,要提前在服务器中准备好被下载的文件,可以在 web 包下建立 files 包,用来存放被下载的文件,此时,被下载的文件地址 path 可以由 request.getServletContext().getRealPath("/files") 得到。
  • 上传是用户通过前端表单操作将文件上传到服务器;
  • 下载是用户点击前端超链接将服务器中的文件下载到浏览器(客户端本地文件)。

注意:

  1. jQuery 官网:https://jquery.com/download/
  2. 需要将 JavaScript 的版本变为 6,方法如下:

  1. 拦截器和文件上传的配置都是在 Spring 的配置文件中,因为都是基于 SpringMVC 框架的。
  2. 搭建完环境,要先测试一下能不能运行,环境是否有问题。
  3. 删除项目中的子模块方法:选中子模块,右键选择 Remove Module 移除模块,然后再右键删除文件夹,注意:要在父模块的 pom.xml 中删除对应的子模块。

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

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

相关文章

mac m1芯片 pytorch安装及gpu性能测试

pytorch 使用mac的m1芯片进行模型训练。 #小结&#xff1a;在数据量小和模型参数少&#xff0c;batch_size小时&#xff0c;cpu训练更快&#xff08;原因&#xff1a;每次训练时数据需要放入GPU中&#xff0c;由于batch_size小。数据放入gpu比模型计算时间还长&#xff09; 在…

【SPI和API有什么区别】

✅什么是SPI&#xff0c;和API有什么区别 ✅典型解析&#x1f7e2;拓展知识仓&#x1f7e2;如何定义一个SPI&#x1f7e2;SPI的实现原理 ✅SPI的应用场景SpringDubbo ✅典型解析 Java 中区分 API和 SPI&#xff0c;通俗的进: API和 SPI 都是相对的概念&#xff0c;他们的差别只…

优化模型:MATLAB整数规划

一、整数规划介绍 1.1 整数规划的定义 若规划模型的所有决策变量只能取整数时&#xff0c;称为整数规划。若在线性规划模型中&#xff0c;变量限制为整数&#xff0c;则称为整数线性规划。 1.2 整数规划的分类 整数规划模型大致可分为两类&#xff1a; &#xff08;1&…

SQL进阶理论篇(二十):什么是SQL注入

文章目录 简介SQL注入的原理SQL注入的实例搭建sqli-labs注入环境实例一&#xff1a;猜测where条件判断查询语句的字段数获取当前数据库和用户信息获取MySQL中的所有数据库名称查询wucai数据库中的所有数据表查询heros数据表中的所有字段参考文献 简介 这节是纯兴趣篇了。 web…

less 查看文本时,提示may be a binary file.See it anyway?

解决办法 首先使用echo $LESSCHARSET查看less的编码 看情况设置less的编码格式(我的服务器上使用utf-8查看中文) 还要特别注意一下&#xff0c;Linux中存在的文本文件的编码一定要是utf - 8;&#xff08;这一步很关键&#xff09; 例如&#xff1a;要保证windows上传到Linux的…

Linux Shell 001-Bash简介

Linux Shell 001-Bash简介 本节关键字&#xff1a;Linux、Bash Shell、shell分类 相关指令&#xff1a;bash、sh、cat Shell的介绍 计算机只能认识&#xff08;识别&#xff09;机器语言(0和1)&#xff0c;如&#xff08;11000000 这种&#xff09;。但是&#xff0c;我们的…

力扣(leetcode)1148和1179题(MySQL)

1148.文章浏览I 题目链接&#xff1a;1148.文章浏览I 解答 # Write your MySQL query statement below select distinct author_id as id from Views where author_idviewer_id order by id;1179.重新格式化部门表 题目链接&#xff1a;1179.重新格式化部门表 解答 …

线程池构造方法的认识

线程池中构造方法的认识 文章目录 线程池中构造方法的认识corePoolSize (核心线程数)maximumPoolSize&#xff08;最大线程数&#xff09;keepAliveTime(非核心线程的空闲超时时间)TimeUnitworkQueuethreadFactoryRejectedExecutionHandler拒绝策略 标准库中提供了一个ThreadPo…

uniapp自定义头部导航怎么实现?

一、在pages.json文件里边写上自定义属性 "navigationStyle": "custom" 二、在对应的index页面写上以下&#xff1a; <view :style"{ height: headheight px, backgroundColor: #24B7FF, zIndex: 99, position: fixed, top: 0px, width: 100% …

RocketMQ实践:确保消息不丢失与顺序性的高效策略

一、使用RocketMQ如何保证消息不丢失&#xff1f; 这个是在面试时&#xff0c;关于MQ&#xff0c;面试官最喜欢问的问题。这个问题是所有MQ都需要面对的一个共性问 题。大致的解决思路都是一致的&#xff0c;但是针对不同的MQ产品又有不同的解决方案。分析这个问题要从以 下几…

汽车服务品牌网站建设的作用是什么

汽车服务涵盖多个层面&#xff0c;在保修维护这一块更是精准到了车内车外&#xff0c;无论是品牌商还是市场中各维修部&#xff0c;都能给到车辆很好的维修养护服务。如今车辆的人均拥有量已经非常高&#xff0c;也因此市场中围绕汽车相关的从业者也比较多。 首先就是拓客引流…

SpringBoot找不到或无法加载主类

1&#xff0c;bug贴图 2&#xff0c;问题说明 之所以导致这个问题是因为新建项目的时候&#xff0c;项目目录是这样的com.lab.hei.springboot.dubbo.ProviderApplication 我觉得这个目录太长了&#xff0c;所以修改了目录&#xff0c;修改后cn.alisa.springboot.dubbo.Provider…

PostGreSQL:货币类型

货币类型&#xff1a;money money类型存储固定小数精度的货币数字&#xff0c;小数的精度由数据库的lc_monetary设置决定。windows系统下&#xff0c;该配置项位于/data/postgresql.conf文件中&#xff0c;默认配置如下&#xff0c; lc_monetary Chinese (Simplified)_Chi…

C++的一些零散小知识

文章目录 1、空指针nullptr的类型为std::nullptr_t2、函数定义中&#xff0c;如果不需要使用参数的值&#xff0c;可以省略参数名3、静态成员变量在C17之后可以直接在类内定义并初始化了 1、空指针nullptr的类型为std::nullptr_t 一个毫无意义的例子&#xff1a; template<…

【Oracle】修改表结构

目录 创建示例1&#xff1a;添加一个或多个列 创建示例2&#xff1a;修改列定义 创建示例3&#xff1a; 删除一列或多列 创建示例4:重命名列 创建示例5:重命名表 创建示例1&#xff1a;添加一个或多个列 -----语法&#xff1a;将新列添加到表中 ALTER TABLE table_name A…

大模型工具_QUIVR

https://github.com/StanGirard/quivr/ 24.5K Star 1 功能 整体功能&#xff0c;想解决什么问题 实现了前后端结合的 RAG 方案。构建能直接使用的应用。提出了“第二大脑”&#xff0c;具体实现也是RAG&#xff0c;但针对不同用户不同场景支持多个“大脑”并存&#xff0c;每个…

css 三角形实现方式及快速联想记忆

css实现三角形是常见的需求&#xff0c;在此记录如下 1 边框实现 原理&#xff1a;相邻的border之间会形成一条斜线(可按此联想记忆) .triangle {width: 0;height: 0;border-left: 100px solid red;border-right: 100px solid green;border-top: 100px solid blue;border-bot…

Spring Boot实践指南

一.SpringBoot入门案例 SpringBoot是由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化Spring应用的初始搭建以及开发过程 原生开发SpringMVC程序过程 在没有SpringBoot前&#xff1a; 1.入门案例开发步骤 &#xff08;1&#xff09;创建新模块&#xff0c;选…

PADS Layout安全间距检查报错

问题&#xff1a; 在Pads Layout完成layout后&#xff0c;进行工具-验证设计安全间距检查时&#xff0c;差分对BAK_FIXCLK_100M_P / BAK_FIXCLK_100M_N的安全间距检查报错&#xff0c;最小为3.94mil&#xff0c;但是应该大于等于5mil&#xff1b;如下两张图&#xff1a; 检查&…