7.1-7.5
实现乘车人信息增删改查
增加乘车人信息表
drop table if exists `passenger`;
create table `passenger` (
`id` bigint not null comment 'id',
`member_id` bigint not null comment '会员id',
`name` varchar(20) not null comment '姓名',
`id_card` varchar(18) not null comment '身份证',
`type` char(1) not null comment '旅客类型|枚举[PassengerTypeEnum]',
`create_time` datetime(3) comment '新增时间',
`update_time` datetime(3) comment '修改时间',
primary key (`id`),
index `member_id_index` (`member_id`)
) engine=innodb default charset=utf8mb4 comment='乘车人';
配置gennerator的配置文件注释掉member,增加Passenger
<table tableName="passenger" domainObjectName="Passenger"/>
新增乘车人类型enum类
package com.fugui.train.member.enums;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
public enum PassengerTypeEnum {
ADULT("1", "成人"),
CHILD("2", "儿童"),
STUDENT("3", "学生");
private String code;
private String desc;
PassengerTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
public static List<HashMap<String,String>> getEnumList() {
List<HashMap<String, String>> list = new ArrayList<>();
for (PassengerTypeEnum anEnum : EnumSet.allOf(PassengerTypeEnum.class)) {
HashMap<String, String> map = new HashMap<>();
map.put("code",anEnum.code);
map.put("desc",anEnum.desc);
list.add(map);
}
return list;
}
}
新增添加乘客接口
从本地线程变量中获取乘客id
common中增加LoginMemberContext线程变量(从中设置和获取用户id)
package com.fugui.train.common.context;
import com.fugui.train.common.commonResp.MemberLoginResp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LoginMemberContext {
private static final Logger LOG = LoggerFactory.getLogger(LoginMemberContext.class);
public static ThreadLocal<MemberLoginResp> member=new ThreadLocal<>();
public static MemberLoginResp getMember(){
return member.get();
}
public static void setMember(MemberLoginResp member){
LoginMemberContext.member.set(member);
}
public static Long getId(){
try {
return member.get().getId();
}catch (Exception e){
LOG.error("获取登录会员信息异常", e);
throw e;
}
}
}
新增MemberInterceptor拦截器,如果用户token存在,则获取并存入线程变量中
package com.fugui.train.common.interceptor;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fugui.train.common.commonResp.MemberLoginResp;
import com.fugui.train.common.context.LoginMemberContext;
import com.fugui.train.common.util.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
public class MemberInterceptor implements HandlerInterceptor {
Logger LOG= LoggerFactory.getLogger(MemberInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//从request取token
String token = request.getHeader("token");
if(StrUtil.isNotBlank(token)){
JSONObject member = JwtUtil.getJSONObject(token);
//如果不为空,记录日志
LOG.info("当前登录用户信息为{}",member);
LOG.info("当前登录token为{}",token);
//把用户信息设置到线程变量中
LoginMemberContext.setMember(JSONUtil.toBean(member, MemberLoginResp.class));
}
return true;
}
}
新增SpringMvcConfig配置过滤器
package com.fugui.train.common.config;
import com.fugui.train.common.interceptor.MemberInterceptor;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {
@Resource
MemberInterceptor memberInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(memberInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(
"/member/member/sendCode",
"member/member/login"
);
}
}
此时已经可以从线程中获取用户id
新增保存用户接口
增加传入类(不需要返回值,不需要返回类),大体和Passenger保持一致,memberId可以不判断是否为空,从线程变量中获取
package com.fugui.train.member.req;
import jakarta.validation.constraints.NotBlank;
import java.util.Date;
public class PassengerSaveReq {
private Long id;
private Long memberId;
@NotBlank(message = "【姓名】不能为空")
private String name;
@NotBlank(message = "【身份证】不能为空")
private String idCard;
@NotBlank(message = "【乘车人类型】不能为空")
private String type;
private Date createTime;
private Date updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getMemberId() {
return memberId;
}
public void setMemberId(Long memberId) {
this.memberId = memberId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", memberId=").append(memberId);
sb.append(", name=").append(name);
sb.append(", idCard=").append(idCard);
sb.append(", type=").append(type);
sb.append(", createTime=").append(createTime);
sb.append(", updateTime=").append(updateTime);
sb.append("]");
return sb.toString();
}
}
PassengerService增加
public void save(PassengerSaveReq req) {
//如果号码存在,返回异常
req.setId(SnowUtil.getSnowflaskNextId());
req.setMemberId(LoginMemberContext.getId());
Date cur = new Date();
req.setCreateTime(cur);
req.setUpdateTime(cur);
Passenger passenger = BeanUtil.copyProperties(req, Passenger.class);
passengerMapper.insert(passenger);
}
PassengerController增加
@Resource
private PassengerService passengerService;
@PostMapping("/save")
public CommonResp save(@Valid@RequestBody PassengerSaveReq req){
passengerService.save(req);
return new CommonResp();
}
增加乘车信息列表及分页查询(部分)
父和子common pom增加依赖
<!-- 分页查询依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.6</version>
</dependency>
增加接受类
package com.fugui.train.member.req;
public class PassengerQueryReq {
private Long memberId;
public Long getMemberId() {
return memberId;
}
public void setMemberId(Long memberId) {
this.memberId = memberId;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", memberId=").append(memberId);
sb.append("]");
return sb.toString();
}
}
增加返回类,考虑到后续可能会展示更多东西(和懒),我就没有删很多字段
package com.fugui.train.member.resp;
import java.util.Date;
public class PassengerQueryResp {
private Long id;
private Long memberId;
private String name;
private String idCard;
private String type;
private Date createTime;
private Date updateTime;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getMemberId() {
return memberId;
}
public void setMemberId(Long memberId) {
this.memberId = memberId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append("Hash = ").append(hashCode());
sb.append(", id=").append(id);
sb.append(", memberId=").append(memberId);
sb.append(", name=").append(name);
sb.append(", idCard=").append(idCard);
sb.append(", type=").append(type);
sb.append(", createTime=").append(createTime);
sb.append(", updateTime=").append(updateTime);
sb.append("]");
return sb.toString();
}
}
增加接口和实现
url规范是字母中间用-连接(这样写总觉得不舒服。。。)
考虑到Service代码需要在admin查询是复用,选择在memberController时就加入用户id这个查询条件,page必须紧跟sql操作,不然不生效
@GetMapping("/query-list")
public CommonResp<List<PassengerQueryResp>> queryList(@Valid PassengerQueryReq req){
if(LoginMemberContext.getMember().getId()!=null){
req.setMemberId(LoginMemberContext.getMember().getId());
}
return new CommonResp<>(passengerService.queryList(req));
}
public List<PassengerQueryResp> queryList(PassengerQueryReq req) {
PassengerExample passengerExample=new PassengerExample();
if(req.getMemberId()!=null){
passengerExample.createCriteria().andMemberIdEqualTo(req.getMemberId());
}
PageHelper.startPage(1,2);
List<Passenger> passengers = passengerMapper.selectByExample(passengerExample);
return BeanUtil.copyToList(passengers, PassengerQueryResp.class);
}
实现分页查询
增加分页查询请求类,请求接口如果有分页需求,可通用继承
package com.fugui.train.common.req;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotNull;
public class PageReq {
@NotNull(message = "【页面】不能为空")
private Integer page;
@NotNull(message = "【每页条数】不能为空")
@Max(value = 100,message = "【每页条数】不能超过100")
private Integer size;
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
@Override
public String toString() {
return "PageReq{" +
"page=" + page +
", size=" + size +
'}';
}
}
封装分页返回类
package com.fugui.train.common.resp;
import java.io.Serializable;
import java.util.List;
public class PageResp<T> implements Serializable {
/**
* 总条数
*/
private Long total;
/**
* 当前页的列表
*/
private List<T> list;
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
@Override
public String toString() {
return "PageResp{" +
"total=" + total +
", list=" + list +
'}';
}
}
对查询方法进行修改,把返回参数封装起来,返回查询条数
public PageResp<PassengerQueryResp> queryList(PassengerQueryReq req) {
PassengerExample passengerExample=new PassengerExample();
if(req.getMemberId()!=null){
passengerExample.createCriteria().andMemberIdEqualTo(req.getMemberId());
}
PageHelper.startPage(req.getPage(),req.getSize());
LOG.info("查询页码:{}", req.getPage());
LOG.info("每页条数:{}", req.getSize());
List<Passenger> passengers = passengerMapper.selectByExample(passengerExample);
PageInfo<Passenger> pageInfo=new PageInfo<>(passengers);
PageResp<PassengerQueryResp> pageResp=new PageResp<>();
pageResp.setTotal(pageInfo.getTotal());
LOG.info("总行数:{}", pageInfo.getTotal());
LOG.info("总页数:{}", pageInfo.getPages());
pageResp.setList(BeanUtil.copyToList(passengers, PassengerQueryResp.class));
return pageResp;
}
修改save方法,使其同时实现update操作
public void save(PassengerSaveReq req) {
Date cur = new Date();
req.setUpdateTime(cur);
//如果用户id存在,则执行更新操作
Passenger passenger = BeanUtil.copyProperties(req, Passenger.class);
if(req.getId()!=null) {
req.setId(SnowUtil.getSnowflaskNextId());
req.setMemberId(LoginMemberContext.getId());
req.setCreateTime(cur);
passengerMapper.insert(passenger);
}else{
passengerMapper.updateByPrimaryKey(passenger);
}
}
新增删除接口
public void delete(Long id) {
passengerMapper.deleteByPrimaryKey(id);
}
@DeleteMapping("/delete/{id}")
public CommonResp<Object> delete(@Valid@PathVariable Long id){
passengerService.delete(id);
return new CommonResp<>();
}