外卖项目笔记
1.SpringBoot启动报错
错误信息:
org.springframework.core.NestedIOException:
ASM ClassReader failed to parse class file
- probably due to a new Java class file version that isn't supported yet
原因:使用了 Spring 不支持的 Java 字节码版本
解决:
将字节码版本降低,我选择 10 后顺利启动

2.MySql报错 ERROR 2003 (HY000)
Can’t connect to MySQL server on ‘localhost’ (10061)
将数据库文件备份好后。
1、首先排除端口被占用导致 Mysql 报错,输入以下命令查看占用 3306 的进程,发现 3306 并没有被占用。
netstat -ano|findstr 3306
2、直接对 MySql 重新初始化,进入 bin 目录(已添加环境变量可直接运行)
net stop mysql // 先停止 MySql 服务
mysqld --initialize --console // 初始化 MySql

启动 MySql 服务
net start mysql
使用新初始化得到的 root 密码登录 mysql 即可,后续记得修改可记忆的密码。
3.拦截未登录用户访问管理页面
两种方法:
- 过滤器
- 拦截器
过滤器:
过滤器类框架
@Slf4j
@WebFilter(filterName = "LoginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("拦截到请求:{}", request.getRequestURI());
filterChain.doFilter(request, response);
}
}
app 类添加注解
@ServletComponentScan
4.密码加密
String password = "123456";
DigestUtils.md5DigestAsHex(password.getBytes())
5.全局异常捕获
新增用户时需要异常捕获
try {
employeeService.save(employee);
} catch (Exception ex) {
R.error("新增失败");
}
而整个项目有很多处需要捕获异常,频繁地使用如上方式,使代码和开发过程变得复杂且重复
编写异常处理类 GlobalExceptionHandler.java
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
// 处理 SQL 异常
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex) {
log.info("捕获到SQL异常");
log.error(ex.getMessage());
return R.error("创建失败..666");
}
}
含有 annotations = {} 中注解的类会被异常处理模块扫描到。这样无论有多少个需要做异常处理的地方,只需要加一句注解即可被扫描到。
不需要自己一个一个写异常处理代码块。
6.列表分页
在员工的 Controller 类里实现分页方法
@GetMapping("/page")
public R<Page> page(int page, int pageSize, String name) {
log.info("分页查询page = {}; pageSize = {}; name = {}", page, pageSize, name);
// 构造分页构造器
Page pageInfo = new Page(page, pageSize);
// 构造条件构造器
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();
// 添加过滤条件
queryWrapper.like(StringUtils.isNotEmpty(name), Employee::getName, name);
queryWrapper.orderByDesc(Employee::getUpdateTime);
// 执行查询
employeeService.page(pageInfo, queryWrapper);
return R.success(pageInfo);
}
其中 R<page> 使用的泛型对象 page 来自于 MybatisPlus 提供的分页插件,概况如下
public class Page<T> implements IPage<T> {
private static final long serialVersionUID = 8545996863226528798L;
protected List<T> records;
protected long total;
protected long size;
protected long current;
protected List<OrderItem> orders;
protected boolean optimizeCountSql;
protected boolean isSearchCount;
protected boolean hitCount;
protected String countId;
protected Long maxLimit;
public Page() {
this.records = Collections.emptyList();
this.total = 0L;
this.size = 10L;
this.current = 1L;
this.orders = new ArrayList();
this.optimizeCountSql = true;
this.isSearchCount = true;
this.hitCount = false;
}
public Page(long current, long size) {
this(current, size, 0L);
}
···
修改用户信息失败

JDBC 报 Update 0 数据没有修改,观察到

请求中的用户 ID 和实际数据库中的 ID 不一致

原因
ID 使用了 Long 型,而 JS 可以处理的最长位数是 16 位,当前 ID 为 19 位,丢失了精度。
- 解决方法:
将 ID 使用对象映射器转换为 String 返回给浏览器
- common 包中创建 JacksonObjectMapper 类
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
//收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
//反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(BigInteger.class, ToStringSerializer.instance)
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//注册功能模块 例如,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
- 在 MvcConfig 重写 extendMessageConverters() 方法
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器..");
// 创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
// 设置对象转换器,使用Jackson将java对象转为Json
messageConverter.setObjectMapper(new JacksonObjectMapper());
// 将转换器对象追加到mvc框架中,排第一个
converters.add(0, messageConverter);
}
此时再做请求时,用户 ID 已经转换为字符串形式,不会产生因 Long 型丢失精度导致的 ID 不存在。


浙公网安备 33010602011771号