JavaWeb(3)-后端web实战

JavaWeb(3)-后端web实战

语雀链接

https://www.yuque.com/yulia-i7t01/qt2ypb/etx8fylzbhvx78aq?singleDoc# 《后端web实战》

Tlias智能学习辅助系统

部门管理

准备工作

Apifox

介绍:Apifox是一款集成了Api文档、Api调试、ApiMock、Api测试的一体化协作平台。

作用:接口文档管理、接口请求测试、Mock服务。

官网:https://apifox.com/

查询部门

接口开发
  • @Autowired:Spring 的自动注入注解,作用是让 Spring 自动创建DeptService的实例对象,并赋值给deptService变量(无需手动new对象,是 Spring “依赖注入” 特性的体现);
  • Result:方法的返回值类型,Result自定义的统一响应类(用于封装接口的返回结果,通常包含 “状态码、提示信息、数据” 三部分);
  • list():方法名,代表 “查询列表” 的功能;方法无参数(因为是查询全部部门,不需要前端传参)。
  • System.out.println("查询全部部门数据");:在服务器控制台打印日志,用于开发阶段调试(方便确认方法是否被触发);
  • List<Dept> deptList = deptService.findAll();
    1. List<Dept>:定义一个 “Dept 类型的集合” 变量deptList,用于存储查询到的所有部门数据;
    2. deptService.findAll():调用服务层DeptServicefindAll()方法,获取数据库中所有部门的列表数据;
  • return Result.success(deptList);
    1. 调用自定义Result类的success静态方法,将查询到的部门列表deptList作为 “响应数据” 传入;
    2. 该方法会返回一个包含 “成功状态码、提示信息、部门数据” 的Result对象,最终被@RestController转换为 JSON 格式返回给前端。

·方式一:手动结果映射-通过@Results及@Result进行手动结果映射

·方式二:起别名-在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样

·方式三:开启驼峰命名-如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射

前后端联调测试

·反向代理

反向代理是一种网络架构,通过代理服务器为后端的服务器做代理,客户端的请求直接请求代理服务器,然后转发给后端的服务器。(安全、灵活、负载均衡)

1.location:用于定义匹配路径匹配的规则。

2.^~/api/:表示精确匹配,即只匹配以/api/开头的路径。

3.rewrite:该指令用于重写匹配到的路径。

4.proxy_pass:该指令用于代理转发,它将匹配到的请求转发给位于后端的指令服务器。

删除部门

(不推荐)

方式二:通过@RequesttParam注解进行参数绑定

推荐方式:如果请求参数名与形参变量名相同,直接定义方法形参即可接收

新增项目

修改部门

查询回显

@PathVariable("id"):Spring 的注解,作用是将路径中{id}对应的参数值,自动赋值给deptId变量

修改数据

@Override —— “我是照着接口的要求写的方法”

  • 大白话:这是一个 “标记注解”,告诉 Java 编译器:“下面这个update方法,不是我随便写的,是照着DeptService接口里定义的update方法来写的”。

日志技术

Logback:在springboot项目中logback依赖已传递

logback.xml

·常用的两种输出日志的位置:控制台、系统文件

·开启日志(ALL),关闭日志(OFF)

日志级别

员工管理

分页查询

代码实现

起始索引=(页码-1)*每页展示记录数

PageHelper分页插件

注意事项:

·定义的SQL语结尾不能加分号

·PageHelper仅仅能对紧跟在其后的第一查询语句进行分页处理

条件分页查询

基本实现

通过@DateTimeFormat解决了 “前端字符串日期→后端日期类型” 的自动转换问题;

程序优化

如果controller方法的参数较多,且未来可能继续增加,这会使得方法签名变得复杂难以维护,此时可以考虑将多个请求参数封装为一个对象。

<if>:判断条件是否成立,如果条件为true,则拼接SQL。

<where>:根据查询条件,来生成where关键字,并会自动去除条件前面多余的and或or。

新增员工

保存员工基本信息
批量保存员工工作经历

<foreach>属性说明:

1.collection:集合名称

2.item:集合遍历出来的元素/项

3.separator:每一次遍历使用的分隔符

4.open:遍历开始前拼接的片段

5.close:遍历结束后拼接的片段

  • collection="exprList":指定要遍历的集合是exprList(这个集合是 Mapper 接口方法传入的参数,比如List<EmpExpr> exprList);
  • item="expr":遍历集合时,当前元素的变量名是expr(后续通过#{expr.empId}取该元素的empId属性);
  • separator=",":每遍历生成一个数据片段后,在后面加一个逗号(用于分隔多条values数据)。

删除员工

·删除单条数据其实是一种特殊的批量删除

SQL语句
三层架构需求分析
Controller层

@RequestParam

·@RequestParam = “精准接收前端 URL 里的参数”

·把 URL 里的参数(page/pageSize/name)精准赋值给后端方法的变量;

·还能设置默认值、指定是否必传,解决参数缺失的问题。

批量删除员工信息
批量删除员工工作经历

修改员工

查询回显
ResultMap

· MyBatis 查询数据库后,默认会把查询结果的 “字段名” 和实体类的 “属性名” 做大小写不敏感的精准匹配

·把数据库查询结果想象成 “快递包裹上的收件人信息(地址写的是‘北京市朝阳区’)”,实体类是 “你的收货地址表单(字段叫‘详细地址’)”:

·没有 ResultMap:快递员只会按 “名字一模一样” 填信息,“朝阳区” 没法对应到 “详细地址”;

·有 ResultMap:你给快递员一张 “规则表”,写着 “包裹上的‘地址’填到表单的‘详细地址’里”,快递员就能精准填对。

Mybatis中封装查询结果,什么时候用 resultType,什么时候用resultMap?

如果查询返回的字段名与实体的属性名可以直接对应上,用resultType。

如果查询返回的字段名与实体的属性名对应不上,或实体属性比较复杂,可以通过resultMap手动封装。

修改数据
@RequestBody

·@RequestBody = “自动把前端传的 JSON 数据,转成后端的 Java 对象”

Spring MVC 中接收前端传入的 JSON 格式请求体的核心注解

Arrays.asList(...):将单个 ID 转换为List集合

rollbackFor = Exception.class:指定 “只要发生任何异常,就回滚事务”

程序优化(动态更新 )

<!--set标签:会自动生成set关键字;会自动的删除掉更新字段后多余,-->

事务管理

介绍&操作

事务 是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作 要么同时成功,要么同时失败。

默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。

Spring事务管理

控制事物

·注解:@Transactional

·作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务

·位置:业务(service)层的方法上、类上、接口上

插件
rollbackFor

·事务管理-默认出现运行时异常RuntimeException才会回滚

·用于控制出现何种异常可以回滚

propagation

·事务传播行为:指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。

四大特性

文件上传

本地存储

1.如何将上传的文件存储在服务器本地?

.multipartFile.getoriginalFilename():获取原始文件名

. multipartFile.transferTo(File dest):将文件转存到磁盘文件

2.上传文件大小受限怎么办?

.默认上传文件的最大大小为1MB,超过大小需要在配置文件配置

阿里云OSS

对象存储OSS(Object Storage Service)

第三方服务-通用思路

准备工作-参照官方SDK(软件开发工作包)编写入门程序-集成使用

@Autowired = “自动找对象并塞给你”

@Autowired是 Spring 框架的核心注解,作用是:让 Spring 自动帮你创建 / 找到需要的对象,然后赋值给你定义的变量,不用你自己手动写new去创建对象

参数配置化

·指将一些需要灵活变化的参数,配置在配置文件中,然后通过@Value注解来注入外部配置的属性

@Value

·是 Spring 框架的注解,作用是把配置文件里的参数值,自动赋值给代码里的变量,相当于 “从配置文件里读数据并填到变量里”。 【 把application.properties(Spring Boot 的配置文件)想象成 “公司的规章制度手册”,@Value就是 “帮你从手册里找到对应的规定,然后告诉你”: 】

·一个属性一个属性的注解

@ConfigurationProperties

·@ConfigurationProperties是 Spring Boot 中批量读取配置文件并封装成对象的注解,比@Value更适合 “读取多个相关配置” 的场景,

· 核心作用:“把配置文件里的一组相关参数,自动打包成一个对象”

· 如果配置文件里有多个同业务的配置项(比如 “阿里云 OSS 存储” 的多个参数),用@Value需要逐个写注解,而@ConfigurationProperties可以 “一次性把这些参数打包成一个对象”,更简洁。

异常处理

全局异常处理器

String message = e.getMessage(); // 获取原始异常信息

int i = message.indexOf("Duplicate entry"); // 找到异常信息的起始位置

String errMsg = message.substring(i); // 截取从“Duplicate entry”开始的内容

String[] arr = errMsg.split(" "); // 按空格分割字符串

@RestControllerAdvice

@RestControllerAdvice是 Spring 的注解,作用是标记一个 “全局异常处理类”,这个类里可以写多个 “处理不同异常的方法”,负责接住整个项目里所有 Controller 抛出的异常。

如果没有@RestControllerAdvice

  • 每个 Controller 的每个方法里,都得写try-catch处理异常,代码会超级冗余(比如 10 个接口就要写 10 次try-catch);

所有异常 “集中处理”,代码只写一次,全项目能用;异常提示统一、友好,用户体验更好。

@ExceptionHandler

@ExceptionHandler是 Spring 的注解,作用是标记在方法上,指定这个方法专门处理 “某一种异常”(比如专门处理 “数据库唯一键冲突异常”、“参数格式错误异常”)。

@ExceptionHandler不能单独用,必须 “放在@RestControllerAdvice标记的类里”—— 相当于 “专科医生必须在急救站里上班,不能自己单独行医”。

@RestControllerAdvice是 “全局异常处理中心的牌子”,@ExceptionHandler是 “中心里的专科医生”—— 两者配合,把项目里所有异常集中接住,转成用户能懂的提示,同时记录日志方便开发排查,是后端项目 “稳定运行 + 友好交互” 的必备配置。

员工信息统计

@NoArgsConstructor

·给类自动生成一个没有任何参数的构造方法(即public 类名())。

·很多框架(比如 Spring、MyBatis)创建对象时,默认需要 “无参构造方法”

@AllArgsConstructor

·给类自动生成一个包含所有属性作为参数的构造方法(参数顺序和类中属性定义顺序一致)

· 创建对象时可以 “一次性给所有属性赋值”,不用写一堆setXxx()方法:

依赖 Lombok:这两个注解是 Lombok 提供的,需要在项目中引入 Lombok 依赖才能生效;

这两个注解经常一起用(既有无参构造满足框架需求,又有全参构造方便创建对象)。

Case函数

·CASE 函数 = SQL 里的 “如果… 就…”

·CASE函数是 SQL 中的 “条件判断工具”,相当于编程里的if-else/switch,能根据不同条件给字段返回不同的值,解决 “按规则转换数据” 的需求。

单条件匹配
多条件判断

职位统计

性别统计

登录认证

会话技术

·会话:用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。

·会话跟踪:一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一浏览器,以便在同一次会话的多次请求间共享数据。

·会话跟踪方案:

·客户端会话跟踪技术:Cookie

·服务端会话跟踪技术:Session

·令牌技术

·跨域区分三个维度:协议、IP/域名、端口

JWT令牌

·全称:JSoN Web Token (https://jwt.io/)

·定义了一种简洁的、自包含的格式,用于在通信双方以json数据格式安全的传输信息。

·组成:

>第一部分:Header(头),记录令牌类型、签名算法等。例如:{"alg":"HS256","type":"JWT"}

>第二部分:Payload(有效载荷),携带一些自定义信息、默认信息等。 例如:{"id":"1","username":"Tom"}

>第三部分:Signature(签名),防止Token被篡改、确保安全性。将header、payload融入,并加入指定秘钥,通过指定签名算法计算而来。

Base64:是一种基于64个可打印字符(A-Z a-z 0-9 +/)来表示二进制数据的编码方式。

JWT令牌由哪几个部分组成,每个部分都存储什么内容?

·header(头),记录令牌类型、签名算法

·payload(载荷),携带一些自定义的信息

·signature(签名),访问被篡改,保证安全性

JWT令牌生成及校验?

Jwts.builder()...

Jwts.parser()...

JWT令牌解析(校验)时什么情况会报错?

JWT令牌被篡改或过期失效了

注意事项

JWT校验时使用的签名秘钥,必须和生成JWT令牌时使用的秘钥是配套的

过滤器(Filter)

·概念:Filter过滤器,是JavaWeb三大组件(Servlet、Filter、Listener)之一。

·过滤器可以把对资源的请求拦截下来,从而实现一些特殊的功能。

·过滤器一般完成一些通用的操作,比如:登录校验、统一编码处理、敏感字符处理等。

1.Filter的开发步骤?

定义:定义一个类实现Filter接口(init、doFilter、destroy)

配置:

@WebFilter(urlPatterns="/*")

@ServletcomponentScan

2.注意事项

如果过滤器中不执行放行操作,过滤器拦截到请求之后,就不会访问对应的资源。

放行:chain.doFilter(request,response)

令牌校验Filter
拦截路径
过滤器链

Interceptor拦截器

“Spring 的配置说明书”

@Configuration是 Spring 框架的核心注解,标记在类上,告诉 Spring:“这个类是一个‘配置类’,里面写了创建对象、配置功能的规则,你要按照这个类里的规则来创建和管理对象”。

日志管理

Read more

OpenWebUI联网搜索实战:如何用SearXNG让本地大模型获取实时信息(附百度/360配置)

OpenWebUI联网搜索实战:如何用SearXNG让本地大模型获取实时信息(附百度/360配置) 如果你在本地运行大模型,比如用Ollama部署了Qwen、Llama或者DeepSeek,可能会发现一个尴尬的问题:模型的知识截止日期是固定的,它不知道今天股市涨跌,不清楚最新的科技新闻,甚至不知道明天是什么节日。这种“信息孤岛”的感觉,让本地大模型的实用性大打折扣。 我最初搭建OpenWebUI环境时,也遇到了这个痛点。看着模型一本正经地分析过时的数据,那种无力感让我开始寻找解决方案。市面上有不少联网搜索方案,但要么配置复杂,要么对国内网络环境不友好。经过几周的折腾和测试,我发现SearXNG这个开源元搜索引擎,配合OpenWebUI的联网搜索功能,是目前最稳定、最灵活的方案之一。 更重要的是,通过合理配置SearXNG,我们可以让本地大模型直接调用百度、360等国内搜索引擎,获取符合中文用户习惯的实时信息。这不仅仅是技术上的连接,更是让本地AI真正“接地气”的关键一步。下面我就把自己踩过的坑、验证过的配置,以及实际效果对比,毫无保留地分享给你。 1. 为什么需要SearXN

什么是weblogic?一文带你了解

什么是weblogic?一文带你了解

Weblogic 简介 WebLogic 是 Oracle 公司开发的一款企业级 Java EE(Java Platform, Enterprise Edition)应用服务器,广泛用于构建、部署和管理分布式应用。它支持高可用性、可扩展性和安全性,适用于大型企业环境。WebLogic 提供了完整的 Java EE 标准实现,包括 Servlet、JSP、EJB、JMS 等技术,同时集成了多种管理工具和监控功能。 Weblogic 核心功能 * Java EE 支持:完全兼容 Java EE 标准,支持企业级应用开发。 * 集群与负载均衡:支持多服务器集群,提供高可用性和故障转移能力。 * 安全性:集成身份认证、授权和加密功能,保障企业数据安全。 * 管理控制台:提供基于 Web

前端国际化:别让你的应用只懂一种语言

前端国际化:别让你的应用只懂一种语言 毒舌时刻 这应用写得跟方言似的,出了本地就没人懂。 各位前端同行,咱们今天聊聊前端国际化。别告诉我你的应用还只有中文版本,那感觉就像在国际会议上只说方言——能说,但没人懂。 为什么你需要国际化 最近看到一个项目,想拓展海外市场,但所有文本都是硬编码在代码里的。我就想问:你是在做本地应用还是在做国际产品? 反面教材 // 反面教材:硬编码文本 function App() { return ( <div> <h1>欢迎来到我的网站</h1> <p>这是一个示例应用</p> <button>点击我</button> <div>

前端团队协作最佳实践:让团队效率飞起来

前端团队协作最佳实践:让团队效率飞起来 毒舌时刻 团队协作?听起来就像是前端工程师为了显得自己很专业而特意搞的一套复杂流程。你以为随便开几个会就能提高团队效率?别做梦了!到时候你会发现,会议时间比开发时间还多,团队效率反而下降了。 你以为使用Git就能解决所有协作问题?别天真了!Git的冲突解决能让你崩溃,分支管理能让你晕头转向。还有那些所谓的协作工具,看起来高大上,用起来却各种问题。 为什么你需要这个 1. 提高开发效率:良好的团队协作可以减少沟通成本,提高开发效率。 2. 减少错误:团队协作可以帮助你发现和修复代码中的错误,减少生产环境中的问题。 3. 知识共享:团队协作可以促进知识共享,提高团队整体水平。 4. 项目管理:良好的团队协作可以帮助你更好地管理项目,确保项目按时完成。 5. 团队凝聚力:良好的团队协作可以增强团队凝聚力,提高团队成员的工作积极性。 反面教材 // 1. 代码冲突 // 开发者A修改了文件 function getUser(id) { return fetch(`/api/users/${id}