day04
1、程序执行逻辑
2、分页处理
package cn.zz.yunhe.study.shequgouv6.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @version 0.01
* @Author yuch
* @Date 2023-08-04 11:52
**/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
// 启用MybatisPlus的拦截器和MybatisPlus优化的分页拦截器PaginationInnerInterceptor
MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
3、异常处理
自定义登录异常类
package cn.zz.study.exception;
/**
* @version 1.0.1
* @Author yuch
* @Date 2023-09-16 11:48
**/
public class LoginException extends BaseException{
public LoginException() {
}
public LoginException(String msg) {
super(msg);
}
}
全局异常处理添加登录异常处理
public Result<String> sqlExceptionHandler(SQLIntegrityConstraintViolationException ex) {
。。。。。。
}
@ExceptionHandler(LoginException.class)
public Result<String> loginExceptionHandler(BaseException ex) {
log.error(ex.getMessage());
//把异常消息转发给前端
return Result.error(ex.getMessage());
}
@ExceptionHandler(BaseException.class)
public Result<String> baseExceptionHandler(BaseException ex) {
。。。。。。。。。
}
把登录业务实现修改为异常方式EmployeeServiceImpl.Java
public Result<Employee> login(EmployeeLoginDto employeeLoginDto) {
//根据用户名和到数据库查数据记录
//创建一个MyBits-plus需要的查询表达式
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
//生成一个根据登录名查用户信息的表达式
queryWrapper.eq(employeeLoginDto.getUsername() != null,
Employee::getUsername, employeeLoginDto.getUsername());
Employee employee = super.getOne(queryWrapper);
String password = employeeLoginDto.getPassword();
if (employee == null) {
throw new LoginException("无此用户,不能登录");
//log.info("无此用户,不能登录");
//return Result.error("无此用户");
}
log.info("库内用户信息={}", employee.toString());
if(!employee.getStatus().equals(StatusConstant.ENABLE)){
throw new LoginException("禁用用户,不能登录");
//log.info("禁用用户,不能登录");
//return Result.error("禁用用户,不能登录");
}
String passwordMW = DigestUtils.md5DigestAsHex(password.getBytes());
if (employee.getPassword().equals(passwordMW)) {
//登录正确
log.info("密码正确,允许登录");
return Result.success(employee);
} else {
//不允许登录
throw new LoginException("密码无误,允许登录");
//log.info("密码无误,允许登录");
//return Result.error("密码错误");
}
}
4、公共字段自动填充
package cn.zz.yunhe.study.shequgouv6.common;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自定义元数据对象处理器
* @author yuch
* @Date 2023-08-19 15:24
*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充(insert)...");
//log.info(metaObject.toString());
if(metaObject.hasGetter("createTime")) {
metaObject.setValue("createTime", LocalDateTime.now());
}
if(metaObject.hasGetter("createUser")) {
//通过BaseContext获取当前用户的ID,然后带入
metaObject.setValue("createUser",BaseContext.getCurrentId());
}
if(metaObject.hasGetter("updateTime")){
metaObject.setValue("updateTime", LocalDateTime.now());
}
if(metaObject.hasGetter("updateUser")){
metaObject.setValue("updateUser", BaseContext.getCurrentId());
}
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充(update)...");
if(metaObject.hasGetter("updateTime")){
metaObject.setValue("updateTime", LocalDateTime.now());
}
if(metaObject.hasGetter("updateUser")){
//通过BaseContext获取当前用户的ID,然后带入
metaObject.setValue("updateUser", BaseContext.getCurrentId());
}
}
}
5、java中线程和进程的区别
在Java中,线程(Thread)是程序执行的最小单位,而进程(Process)是操作系统分配资源的最小单位。下面是线程和进程的区别:
1. 定义:一个进程可以包含多个线程,每个线程拥有自己的执行路径。进程是一个独立运行的程序,具有独立的地址空间和系统资源。线程是进程内的一条执行路径,多个线程共享同一进程的地址空间和系统资源。
2. 单位:进程是操作系统为了完成任务而设置的执行实体,可以独立地执行和资源调度。线程是进程内的一个实体,是CPU调度和分派的基本单位。
3. 资源占用:进程拥有独立的内存空间和系统资源,如文件句柄、网络端口等。不同进程间的资源相互隔离,需要通过进程间通信来实现数据共享。线程共享进程的内存空间和系统资源,包括堆内存、文件句柄等。线程间可以直接共享数据,不需要额外的通信机制。
4. 创建和销毁:创建和销毁一个进程的开销通常比较大,涉及到操作系统内核的介入。创建和销毁一个线程的开销相对较小,通常在进程内通过调用线程库的API即可完成。
5. 并发性:多个进程可以并发执行,在多核系统中可以并行执行。一个进程内的多个线程可以同时执行,共享进程的资源。
6. 稳定性:一个进程崩溃通常不会影响其他进程的执行。一个线程崩溃可能会导致整个进程的崩溃。
7. 通信和同步:进程间的通信比较复杂,可以使用进程间通信(IPC)机制来进行数据交换。线程间的通信和同步比较简单,可以使用共享内存、信号量等机制来实现。
总的来说,进程是资源分配的最小单位,线程是独立执行的最小单位。线程的创建、切换和销毁开销小,但需要注意线程之间的同步和共享资源的安全性,而进程的创建和销毁开销较大,但是相对独立和稳定,资源隔离相对较好。在Java中,通过线程和多线程编程,可以实现并发处理和提高程序的执行效率。
ThreadLocal是Java中用于在多线程环境下保持线程数据隔离的工具类。它可以使得每个线程都拥有独立的变量副本,从而解决了线程和进程间数据共享和安全性的问题。
使用ThreadLocal时,每个线程都可以通过ThreadLocal对象来获取一个针对该线程的独立变量副本。这个独立的变量副本在不同的线程之间互不干扰,每个线程都可以独立修改和访问自己的副本。
ThreadLocal的主要解决的问题包括以下两个:
1. 线程间数据隔离:由于每个线程都会拥有独立的ThreadLocal变量副本,各个线程可以独立地修改和访问该副本,不会影响其他线程的数据。
2. 线程安全性:通过将变量存储在ThreadLocal中,可以避免对共享变量进行同步操作,从而提高多线程环境下程序的并发性能和效率。
例如,如果多个线程需要访问同一个线程不安全的对象时,可以使用ThreadLocal将该对象创建为每个线程独立的副本,这样每个线程都拥有自己的独立对象,从而避免了对该对象进行同步操作。
需要注意的是,虽然ThreadLocal可以解决线程间数据共享和安全性的问题,但在使用过程中也需要注意合理使用,避免滥用,否则可能会导致资源泄露和内存溢出等问题。同时,需要及时清理ThreadLocal对象,以避免内存泄漏。