tlias 智能管理系统

tlias智能管理系统

跟着老师敲了部门管理和员工管理的内容

以下是自己写班级管理,学员管理,数据统计的历程

故余虽愚,卒获有所闻

因为在写代码的过程中发现就是简单的copy代码,所以这里没有提供更多的代码思路,详情请看github中具体的commit,那里会有详细注释解析

代码仓库: tlias管理系统-黑马程序员2024JavaWeb+AI 实训 (github.com)

前端代码仓库:lyay23/vue-tlias-management: tlias的前端部分

一、代码开发

1、班级管理

1.1 分页查询功能

劳资不会怎么办 不管了先写在说

一个很不好的问题,我的Controller要叫什么名字

ClazzController

package com.itheima.controller;

import com.itheima.pojo.Clazz;
import com.itheima.pojo.ClazzQueryParam;
import com.itheima.pojo.PageResult;
import com.itheima.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* Created with IntelliJ IDEA.
*
* @Author: 李阳
* @Date: 2025/04/07/13:23
* @Description: 班级管理的一些列操作
*/

@RestController
@Slf4j
@RequestMapping("/clazzs")
public class ClazzController {

/**
* 班级管理--分页查询
*/
@GetMapping
public Result page(ClazzQueryParam clazzQueryParam){
log.info("分页查询班级信息,参数:{}", clazzQueryParam);
PageResult<Clazz> pageResult= clazzService.page(clazzQueryParam);
return Result.success(pageResult);
}

}

分页查询功能,我先写的controller,

操他奶奶的,控制台一直报错

Method parameter 'id': Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; For input string: "list"

劳资找了一下午错误,后面发现是方法上没加**@GetMapping**注解

代码基本上完成了,下面我们一起看看具体的实现

ClazzController

@RestController
@Slf4j
@RequestMapping("/clazzs")
public class ClazzController {

@Autowired
private ClazzService clazzService;

/**
* 班级管理--分页查询
*/
@GetMapping
public Result page(ClazzQueryParam clazzQueryParam) {
log.info("分页查询班级信息,参数:{}", clazzQueryParam);
PageResult<Clazz> pageResult = clazzService.page(clazzQueryParam);
return Result.success(pageResult);
}
}

参照那个部门的分页查询,基本代码一样,就修改了泛型 还有clazzQueryParam

clazzQueryParam

package com.itheima.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;

/**
* Created with IntelliJ IDEA.
*
* @Author: 李阳
* @Date: 2025/04/07/13:29
* @Description: 分页查询实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClazzQueryParam {
private String name;
private LocalDate begin;
private LocalDate end;
private Integer page=1;
private Integer pageSize=10;
}

参照的接口文档,返回来的数据

service代码可以一键配置,这里不再多说

ClazzServiceImpl

@Autowired
private ClazzMapper clazzMapper;


/**
* 分页查询
*/
@Override
public PageResult<Clazz> page(ClazzQueryParam clazzQueryParam) {
//1.设置分页参数
PageHelper.startPage(clazzQueryParam.getPage(),clazzQueryParam.getPageSize());
//2.调用分页查询的方法
List<Clazz> clazzList = clazzMapper.list(clazzQueryParam);
//3.封装结果并返回
Page<Clazz> pageResult = (Page<Clazz>) clazzList;
return new PageResult (pageResult.getTotal(),pageResult.getResult());
}

还是抄的代码,基本上没有改,就改了泛型

ClazzMapper.xml

<!--分页条件查询-->
<select id="list" resultType="com.itheima.pojo.Clazz">
select c.*, e.name masterName,
(case when begin_date > now() then '未开班' when now() > end_date then '已结课' else '在读中' end) status
from clazz as c left join emp e on c.master_id = e.id
<where>
<if test="name != null and name != ''">
c.name like concat('%',#{name},'%')
</if>
<if test="begin !=null and end != null">
and c.end_date between #{begin} and #{end}
</if>
</where>
order by c.update_time desc
</select>

我们重点看一下xml语句,多了一个case,后面做了一个模糊查询,把开始时间结束时间和名称做了模糊查询,挺厉害的

我没有想到可以用case,我第一次思考的时候是用if语句

失之毫厘 差之千里

又因为大小写报错解决了半个小时的问题我草了

后面都是很简单的代码操作,基本上就是抄抄抄的代码,具体看github的commit

2.学员管理

1.分页查询

我在写分页查询时遇到了一些错误,控制台报错:

Validation failed for argument [0] in public com.itheima.pojo.Result com.itheima.controller.StudentController.page(com.itheima.pojo.StudentQueryParam): [Field error in object 'studentQueryParam' on field 'clazzId': rejected value [null]; codes [typeMismatch.studentQueryParam.clazzId,typeMismatch.clazzId,typeMismatch.java.lang.Integer,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [studentQueryParam.clazzId,clazzId]; arguments []; default message [clazzId]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' for property 'clazzId'; For input string: "null"]] 
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:158) ~[spring-web-6.2.5.jar:6.2.5]
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122) ~[spring-web-6.2.5.jar:6.2.5]
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:227) ~[spring-web-6.2.5.jar:6.2.5]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:181) ~[spring-web-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986) ~[spring-webmvc-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891) ~[spring-webmvc-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.2.5.jar:6.2.5]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.2.5.jar:6.2.5]

好像是前端传的是null没办法转为Integer类型,一直未解决

也就是我的所属班级模块一直是错误的

奶奶的又找了一个小时的错误,后面看接口文档感觉像是班级管理模块的问题,一检查,查询所有班级模块没有加id,怪不得前端获取不到id,因为我都根本没有查,

感觉自己是一头猪,再也不自己想代码了,一定要好好参考文档

班级管理之类的代码也很简单,基本就是操操操,代码详情请看GitHub的commit


3. 登录功能

在 Java 中,过滤器和拦截器的区别如下:

  1. 所属规范与使用范围:过滤器属于 Servlet 规范,可拦截进入容器的所有请求,包括静态和动态资源请求;拦截器通常是 Spring 框架的功能,只能拦截 Spring 管理的 Bean 所处理的请求,一般不拦截静态资源请求。
  2. 实现方式:过滤器需实现 javax.servlet.Filter 接口,重写 doFilter、init 和 destroy 方法;拦截器需实现 org.springframework.web.servlet.HandlerInterceptor 接口,重写 preHandle、postHandle 和 afterCompletion 方法。
  3. 执行时机:过滤器在 Servlet 处理请求之前和之后执行;拦截器的 preHandle 在 Controller 处理请求之前执行,postHandle 在 Controller 处理请求之后、视图渲染之前执行,afterCompletion 在视图渲染之后执行。
  4. 依赖注入:过滤器中不能直接使用 Spring 的依赖注入;拦截器是 Spring 组件,可以方便地使用 Spring 的依赖注入。
  5. 作用对象:过滤器作用于 Servlet 容器,对所有符合条件的请求都起作用;拦截器作用于 Spring 框架的处理器映射器(HandlerMapping)返回的处理器(Handler),针对特定的请求处理逻辑。

二、AOP

AOP: Aspect Oriented Programming(面向切面编程、面向方面编程),可简单理解为就是面向特定方法编程。AOP的底层就是动态代理技术

概念

场景∶案例中部分业务方法运行较慢,定位执行耗时较长的方法,此时需要统计每一个业务方法的执行耗时

  • 连接点: JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
  • 通知:Advice,指那些重复的逻辑,也就是共性功能(最终体现为一个方法)
  • 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用,实际被aop控制的方法
  • 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
  • 目标对象:Target,通知所应用的对象

通知

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行 ,返回值类型必须为object,需要手动调用proceed方法
  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行
  • @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有虽常都会执行
  • @AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
  • @AfterThrowing :异常后通知,此注解标注的通知方法发生异常后执行

通知执行顺序

  • 当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行。

  • 执行顺序:

    • 不同切面类中,默认按照切面类的类名字母排序:

    • 目标方法前的通知方法:字母排名靠前的先执行

    • 目标方法后的通知方法:字母排名靠前的后执行

@pointCut

image-20250410195911547

切入点表达式

image-20250410200735189

  • execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:

​ execution(包名.类名)

​ *∶单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分

​ …∶多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数

image-20250410201243358

连接点

在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。

  • 对于@Around 通知,获取连接点信息只能使用ProceedingJoinPoint

  • 对于其它四种通知,获取连接点信息只能使用JoinPoint,它是 ProceedingJoinPoint的父类型

JoinPoint

image-20250410203556008

三、SpringBoot零碎知识点

1. 配置优先级

properties> yml > yaml,一般使用yml

2. Bean管理

@Scope()

image-20250411093330523

四、Docker入门

致谢

感谢黑马,感谢涛哥,感谢idea,感谢通义千问,感谢github上同样写这个项目的小伙伴

这个小项目在2025/4/10 23点正式完结

虽然只是一个很小很小的小项目,不过确实收获了很多,了解了很多关于Spring的注解,以及类之间的关系

没做这个小项目之前我基本上什么都不太明白,做完感觉对整个项目结构更清晰了

​ 2025/4/10