当前位置: 首页 > news >正文

苍穹外卖笔记集锦

Build 建造者模式
  • Lombok提供
实现:

在类上添加 @Builder 注解:

import lombok.Builder;
import lombok.Data;@Data
@Builder
public class EmployeeLoginVO {private Long id;private String userName;private String name;private String token;
}

使用 Builder 创建对象

EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder().id(employee.getId()).userName(employee.getUsername()).name(employee.getName()).token(token).build();
多个pom文件的管理

使用父POM<dependencyManagement>: 只在父级pom文件中添加.
如果在子pom中多次添加,可能会导致不能启动项目的问题.

maven聚合工程
  • 聚合器POM(父工程)
    聚合工程中要指定<packaging>pom,用于聚合多个模块,并通过 <dependencyManagement> 锁定各个依赖版本。并在<modules>标签内列出所有的子模块

  • 模块间的依赖
    如果一个子模块需要依赖另一个子模块,在pom.xml中添加对该子模块的依赖:​

<dependency><groupId>com.example</groupId><artifactId>module1</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
  • 聚合器模块不要作为依赖:

    <dependency><groupId>Warren</groupId><artifactId>Common</artifactId><version>0.0.1-SNAPSHOT</version>
    </dependency>
    

Common模块是一个POM类型的聚合器(包含Common-utilService-util)。聚合器模块一般不产生jar包,作为依赖引用可能会引起问题;如果需要使用,引用聚合器的具体模块(例如Common-utilService-util)即可.

Query参数
  • URL? 后面的键值对传递的请求参数。比如/employee/page?name=zhangsan 中的name=zhangsan 就是Query参数。

  • 使用@RequestParam 注解来获取Query参数

Pagehelper分页

PageHelper是由GitHub上的pagehelper组织维护的MyBatis通用分页插件。

  • 使用这个方法之后就不用导入MP的配置类了

  • PageHelper.startPage(page, pageSize) : page 表示当前页码,pageSize 是每页显示的记录数。

  • 在调用该方法之后,紧跟着执行的查询会被拦截,并在生成的SQL中添加分页相关的语句,注意后面跟随的方法要返回一个Page

PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());  Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);//后续定义

需要导入依赖:

<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version>
</dependency>
生成主键

MyBatisXML映射文件中的两个属性

  • useGeneratedKeys="true"
    自动生成主键。并在执行插入操作后,返回主键id

  • keyProperty="id"
    指定生成的主键值应对应到Java对象中的哪个属性上。

设置时间自动填充:
  • 在数据库表中设置时间自动填充,就不用在实体类上指定自动填充时间了

  • 数据库中时间类字段使用timestamp,实体类中使用String.

`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
jackson:  date-format: yyyy-MM-dd HH:mm:ss  time-zone: GMT+8

设置时间正确显示,如果不加这个配置,时间显示的不是中国时间.

使用AOP实现公共字段填充

实现思路:

  1. 自定义一个注解 @AutoFill用于标识需要自动填充公共字段的方法,并指定对应的数据库操作类型(INSERTUPDATE)。

  2. 定义枚举 OperationType:枚举数据库操作类型,包括INSERTUPDATE

  3. 创建切面类 AutoFillAspect:在该切面中,拦截标注了@AutoFill注解的方法,获取方法参数(即实体对象),并通过反射为其公共字段赋值。

具体步骤:

  1. 定义 @AutoFill 注解:

    import com.sky.enumeration.OperationType;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;@Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AutoFill {//指定数据库操作类型:INSERT或UPDATEOperationType value();
    }
    
  2. 定义枚举:

  package com.sky.enumeration;public enum OperationType {     INSERT,UPDATE}
  1. 创建切面类 AutoFillAspect

    package com.sky.aspect;import com.sky.annotation.AutoFill;
    import com.sky.constant.AutoFillConstant;
    import com.sky.context.BaseContext;
    import com.sky.enumeration.OperationType;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    import java.lang.reflect.Method;
    import java.time.LocalDateTime;/*** 切面类,实现公共字段的自动填充*/
    @Aspect
    @Component
    @Slf4j
    public class AutoFillAspect {/*** 定义切入点,拦截所有在mapper包下,标注了@AutoFill注解的方法*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut() {}/*** 前置通知,在方法执行前进行公共字段的赋值*/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("开始进行公共字段自动填充...");// 获取被拦截的方法签名MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 获取方法上的@AutoFill注解AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);// 获取数据库操作类型OperationType operationType = autoFill.value();// 获取方法参数,即实体对象Object[] args = joinPoint.getArgs();if (args == null || args.length == 0) {return;}Object entity = args[0];// 获取当前时间和当前用户IDLocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();try {if (operationType == OperationType.INSERT) {// 插入操作,设置创建和更新相关字段setFieldValue(entity, AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class, now);setFieldValue(entity, AutoFillConstant.SET_CREATE_USER, Long.class, currentId);setFieldValue(entity, AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class, now);setFieldValue(entity, AutoFillConstant.SET_UPDATE_USER, Long.class, currentId);} else if (operationType == OperationType.UPDATE) {// 更新操作,设置更新时间和更新人字段setFieldValue(entity, AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class, now);setFieldValue(entity, AutoFillConstant.SET_UPDATE_USER, Long.class, currentId);}} catch (Exception e) {log.error("公共字段自动填充失败", e);}}/*** 通过反射为实体对象的指定字段赋值*/private void setFieldValue(Object entity, String methodName, Class<?> parameterType, Object value) throws Exception {Method method = entity.getClass().getDeclaredMethod(methodName, parameterType);method.invoke(entity, value);}
    }
    

说明:

  • @Pointcut:定义切入点,拦截com.sky.mapper包下所有标注了@AutoFill注解的方法。

  • @Before:在目标方法执行前进行公共字段的赋值操作。

  • setFieldValue方法:通过反射调用实体对象的setter方法,为公共字段赋值。

  1. Mapper方法上使用 @AutoFill 注解:

    package com.sky.mapper;import com.sky.annotation.AutoFill;
    import com.sky.entity.Employee;
    import com.sky.enumeration.OperationType;
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Update;@Mapper
    public interface EmployeeMapper {/*** 插入员工数据*/@Insert("INSERT INTO employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user, status) " +"VALUES (#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser}, #{status})")@AutoFill(OperationType.INSERT)void insert(Employee employee);/*** 更新员工数据*/@Update("UPDATE employee SET name = #{name}, username = #{username}, password = #{password}, phone = #{phone}, sex = #{sex}, id_number = #{idNumber}, " +"update_time = 
    

HttpClient

  • 用于在java程序中构造并发送http请求

![[Pasted image 20250326094121.png]]

第三方 HTTP 客户端库 Apache HttpComponents
  1. HttpClient

    • 提供HTTP客户端相关的核心功能,比如创建请求、发送请求、处理响应、连接池管理等。
  2. HttpCore

    • 提供低层次的HTTP传输组件和协议处理,HttpClient库在此之上进行更高级封装。
  3. HttpMime

    • 用于处理多部分(multipart)请求或文件上传等场景。

引入依赖:

<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
主要类:

CloseableHttpClient:

最核心的客户端类,负责创建并执行请求。获取方式:

CloseableHttpClient httpClient = HttpClients.createDefault();

也可以使用 HttpClientBuilder 自定义配置:

CloseableHttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(100)            // 设置最大连接数.setMaxConnPerRoute(20)          // 每个路由的最大连接数// ... 其他自定义配置.build();

请求方法

  • HttpGet:执行 GET 请求,不带请求体

  • HttpPost:执行 POST 请求,可带表单或 JSON 等请求体

  • HttpPut:执行 PUT 请求

  • HttpDelete:执行 DELETE 请求

  • HttpPatch:执行 PATCH 请求(需要 4.2+ 版本支持)

    /*** 测试通过httpclient发送GET方式的请求*/@Testpublic void testGET() throws Exception{//创建httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();//创建请求对象HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");//发送请求,接受响应结果CloseableHttpResponse response = httpClient.execute(httpGet);//获取服务端返回的状态码int statusCode = response.getStatusLine().getStatusCode();System.out.println("服务端返回的状态码为:" + statusCode);HttpEntity entity = response.getEntity();String body = EntityUtils.toString(entity);System.out.println("服务端返回的数据为:" + body);//关闭资源response.close();httpClient.close();
}
/*** 测试通过httpclient发送POST方式的请求*/@Testpublic void testPOST() throws Exception{// 创建httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();//创建请求对象HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");JSONObject jsonObject = new JSONObject();jsonObject.put("username","admin");jsonObject.put("password","123456");StringEntity entity = new StringEntity(jsonObject.toString());//指定请求编码方式entity.setContentEncoding("utf-8");//数据格式entity.setContentType("application/json");httpPost.setEntity(entity);//发送请求CloseableHttpResponse response = httpClient.execute(httpPost);//解析返回结果int statusCode = response.getStatusLine().getStatusCode();System.out.println("响应码为:" + statusCode);HttpEntity entity1 = response.getEntity();String body = EntityUtils.toString(entity1);System.out.println("响应数据为:" + body);//关闭资源response.close();httpClient.close();}

文件上传(HttpMime)

如果要上传文件,可以使用 HttpMime 提供的 MultipartEntityBuilder

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("description", "测试文件");
builder.addBinaryBody("file", new File("test.png"), ContentType.DEFAULT_BINARY, "test.png");
HttpEntity multipart = builder.build();HttpPost httpPost = new HttpPost("https://example.com/upload");
httpPost.setEntity(multipart);
// 执行并处理响应
MyBatis条件查询问题
List<Dish> list(Dish dish);
<select id="list" resultType="com.sky.entity.Dish" parameterType="com.sky.entity.Dish">  select * from dish    <where>  <if test="name != null">  and name like concat('%',#{name},'%')        </if>  <if test="categoryId != null">  and category_id = #{categoryId}       </if>  <if test="status != null">  and status = #{status}       </if>  </where>  order by create_time desc</select>

这里虽然只传入了一个dish参数,但是MyBatis在 SQL 里会使用 dish 的属性来构造查询条件.

Redis 匹配模式
  • *
    匹配任意数量的字符(包括空字符)。
    例如:

    • user* 能匹配所有以 “user” 开头的键,如 user1username 等。
  • ?
    匹配任意一个单独的字符。
    例如:

    • user? 可以匹配 user1userA,但不能匹配 user12user
  • [abc]
    匹配方括号中任意一个字符。
    例如:

    • user[123] 可以匹配 user1user2user3
  • [a-z]
    通过指定一个字符范围,匹配该范围内的任意字符。
    例如:

    • file[0-9] 能匹配 file0file9 之间的任何一个文件名。
Spring el表达式

使用注解(比如 @Cacheable@CacheEvict@CachePut)进行缓存操作时,需要通过SpEL动态计算缓存键(key)或执行条件(condition )。

key 属性指定生成缓存键的规则
condition 属性指定执行缓存操作的条件

@Cacheable(value = "users",key = "#id",               // 使用 SpEL,生成 keycondition = "#id > 0"      // 只有当 id>0 时才执行缓存
)
public User getUserById(int id) {// ...return user;
}
  • key = "#id" 表示缓存键就是方法第一个参数 id 的值。
  • 如果不指定 key,默认情况下Spring会将所有方法参数组合起来作为缓存键。
访问方法参数
@Cacheable(value = "users", key = "#p0") 
public User findUserById(Long id) {// ...
}
  • #p0#a0 都表示第一个参数 id 的值。第二个是#p1#a1.
使用方法的返回值做缓存键:
@CachePut(value = "users", key = "#result.id")
public User updateUser(User user) {// 修改用户并返回更新后的 userreturn user;
}
  • 这里 #result 是方法的返回值 User,再取 id 作为缓存键。

使用 condition 属性来决定是否执行缓存操作:

@Cacheable(value = "numbers", key = "#number", condition = "#number > 10")
public int processNumber(int number) {// 只有当 number > 10 时才会执行缓存return number * 2;
}
spring task
  • 任务调度工具,按照约定时间自动执行代码逻辑

![[Pasted image 20250329155525.png]]

周的位置表示星期几,日和周一般只出现一个,另一个使用?表示,因为不能保证某一天的具体是星期几

![[Pasted image 20250329160343.png]]

websocket
  • 一次握手实现双向数据传输
apache poi
  • 读写excel,word等文件
日期相关
  • 指定参数中日期的格式
@DateTimeFormat(pattern = "yyyy-MM-dd")  LocalDate begin,  
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end
  • 获得某一天的起始时间和结束时间,即0时0分0秒和23时59分59秒
LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);  
LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
使用map作为sql查询参数

MyBatis中传入一个 Map 作为参数时,MyBatis会将 Map中的键key视为参数名

Map map = new HashMap();
map.put("begin", beginTime);
map.put("end", endTime);
map.put("status", Orders.COMPLETED);
Double turnover = orderMapper.sumByMap(map);
<select id="sumByMap" resultType="java.lang.Double">  select sum(amount) from orders   <where>  <if test="begin != null">  and order_time > #{begin}  </if>  <if test="end != null">  and order_time < #{end}  </if>  <if test="status != null">  and status = #{status}        </if>  </where>  
</select>
StringUtils.join()拼接方法
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;public class JoinExample {public static void main(String[] args) {// 使用 List 拼接List<String> list = new ArrayList<>();list.add("张三");list.add("李四");list.add("王五");String joinedList = StringUtils.join(list, ",");System.out.println("拼接后的 List:" + joinedList); // 输出:张三,李四,王五// 使用数组拼接String[] arr = {"苹果", "香蕉", "橘子"};String joinedArray = StringUtils.join(arr, "-");System.out.println("拼接后的数组:" + joinedArray); // 输出:苹果-香蕉-橘子}
}
http://www.lryc.cn/news/599546.html

相关文章:

  • 图像梯度处理与边缘检测
  • 储粮温度预测新方案!FEBL模型用代码实现:LSTM+注意力+岭回归的完整流程
  • 剖析 Web3 与传统网络模型的安全框架
  • Idefics3:构建和更好地理解视觉-语言模型:洞察与未来方向
  • 使用 FFmpeg 实现 RTP 音频传输与播放
  • 视频质量检测效率提升28%!陌讯多模态融合方案在流媒体场景的技术实践
  • JAVA + 海康威视SDK + FFmpeg+ SRS 实现海康威视摄像头二次开发
  • Spring 生态创新应用:现代架构与前沿技术实践
  • C++常见面试题之一
  • [NLP]UPF基本语法及其在 native low power verification中的典型流程
  • 【JavaEE】Spring Web MVC(上)
  • 焊接机器人节能先锋
  • 协作机器人掀起工厂革命:码垛场景如何用数据重塑制造业命脉?
  • MCP (Model Context Protocol) 与 HTTP API:大模型时代的通信新范式
  • 滚珠导轨:手术机器人与影像设备的精密支撑
  • 草木知音的认知进化:Deepoc具身智能如何让除草机器人读懂大地密语
  • [特殊字符] VLA 如何“绕过”手眼标定?—— 当机器人学会了“看一眼就动手”
  • [python][flask]flask蓝图使用方法
  • [python][flask]flask中session管理
  • 从 “能打” 到 “顶尖”:DeepSeek-V3 后训练拆解,微调 + 强化学习如何让大模型脱胎换骨?
  • 【js】Proxy学习笔记
  • spring boot项目使用Spring Security加密
  • HTML 常用标签速查表
  • 【STM32】FreeRTOS任务的挂起与解挂(四)
  • ServletRegistrationBean相关知识点
  • IIC协议详解与项目注意事项
  • Ant Design 结合 React 参考 Vben 逻辑实现的描述列表组件封装实践
  • C#模拟pacs系统接收并解析影像设备数据(DICOM文件解析)
  • 【unitrix】 6.16 非负整数类型( TUnsigned )特质(t_unsingned.rs)
  • Docker镜像导入解析:docker import vs docker load