新增
@PostMapping
public R<String> save(@RequestBody Employee employee, HttpServletRequest request) {
log.info("新增员工 {}", employee.toString());
//初始密码,加密处理
employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
//员工信息补全
Long empId = (Long) request.getSession().getAttribute("employee");
employee.setCreateUser(empId);
employee.setUpdateUser(empId);
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
employeeService.save(employee);
log.info("新增员工成功");
return R.success("新增员工成功");
}
全局异常设置
/**
* 全局异常处理类
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class}) //通知,拦截类上加了@RestController,@Controller注解的异常
@ResponseBody//返回Json格式
@Slf4j
public class GlobalExceptionHandler {
/**
* 差异处理方法
* @return
*/
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
log.error(ex.getMessage());
if (ex.getMessage().contains("Duplicate entry")){ //sql返回的username重复错误提示
String[] split = ex.getMessage().split(" ");
String msg = split[2]+"已存在";
return R.error(msg);
}
return R.error("未知错误");
}
}
分页查询
1.配置拦截器
/**
* 配置分页插件
*/
@Configuration
public class MybatisPlusConfig {
/**
* 添加分页拦截器
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
2.分页查询
/**
* 分页查询
* @param page
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page") //http://localhost:8080/employee/page?page=1&pageSize=10&name=
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);//pageInfo已封装数据
return R.success(pageInfo);
}
用户根据Id的update接口
@PutMapping
public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
log.info("修改{}",employee.getId());
employee.setUpdateTime(LocalDateTime.now());
employee.setUpdateUser((Long) request.getSession().getAttribute("employee"));
employeeService.updateById(employee);
return R.success("员工已更新");
}
Long型数据响应到页面只能保证16位的精度,
修复步骤
1,提供JacksonObjectMapper,其还可以对LocalDateTime序列化为xxxx年xx月休息日
2在WebMvcConfig配置扩展Spring mvc消息转化器,加入acksonObjectMapper
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);
}
}
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 设置静态资源
*
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始静态资源映射配");
//请求路径xxx/backed/xxx指向静态资源calsspath:/backed/
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
//同理
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
/**
* 扩展mvc的消息转换器
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
//设置对象转换器,用Json将java格式转换
messageConverter.setObjectMapper(new JacksonObjectMapper());
//将转换器添加到mvc框架的转换器集合中
converters.add(0,messageConverter); //0为加到开头
}
编辑数据,先根据Id查询,在调用已写的修改接口即可
@GetMapping("/{id}")
public R<Employee> getById(@PathVariable int id){
log.info("准备修改id:{}数据",id);
Employee employee = employeeService.getById(id);
return R.success(employee);
}
mybayide-plus提供字段自动填充
1.实体类加入@TableField注解
2.编写元数据对象处理器,统一为公共字段赋值,此类实现接口
如下:
@TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.UPDATE) private LocalDateTime updateTime;
/**
* 自定义元数据对象处理器
*/
@Component //交给spring处理
@Slf4j
public class MyMetObjectthandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("公共字段自动填充[insert]");
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("createUser", BaseContext.getCurrentId());
metaObject.setValue("updateUser", BaseContext.getCurrentId());
log.info(metaObject.toString());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("公共字段自动填充[update]");
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("updateUser", BaseContext.getCurrentId());
log.info(metaObject.toString());
}
}
http请求的,对应服务会分配新线程,为获得修改人Id可以使用 ThreadLocal在用户登入时保存Id,使用时获取以下为ThreadLocal使用和登入代码修改
/**
* 基于Local封装工具类,用于保持用户登入Id
*/
public class BaseContext {
private static ThreadLocal<Long> threadLocal =new ThreadLocal<>();
public static void setCurrentId(Long id){
threadLocal.set(id);
}
public static Long getCurrentId(){
return threadLocal.get();
}
}
//4.判断是否登入。登入放行
Object employee = request.getSession().getAttribute("employee");
if (employee!=null){
BaseContext.setCurrentId((Long) employee);//当前登入用户的线程存入Id到ThreadLocal的副本中
filterChain.doFilter(request,response);
log.info("Id:{}已登入",employee);
return;
}