苍穹外卖02(新增员工,重复内容异常处理器,绑定当前用户ThreadLocal,日期格式问题,分页查询,启用禁用,编辑员工)

目录

一、员工管理-新增员工

1.需求分析和设计

2.代码开发

3 功能测试

接口文档测试

前后端联调测试

4 代码完善一:增加异常处理器

5 代码完善二:绑定当前用户名

(1) 准备ThreadLocal工具类

(2) 修改拦截器代码

(3) Service里获取当前用户

小结

二、员工管理-分页查询

1.需求分析和设计

2 代码开发

3 功能测试

 4.问题描述:操作时间字段显示有问题。

三、员工管理-启用禁用

1 需求分析与设计

2 代码开发

3 功能测试

四、员工管理-编辑员工

1 需求分析与设计

2 代码开发

3 功能测试


一、员工管理-新增员工

准备工作:

  1. 先把服务端启动:运行引导类

  2. 再把nginx启动:双击nginx.exe,去任务管理器里查看一下,如果有两个nginx进程就说明启动成功了

开发功能时的依赖:

  • 接口文档

1.需求分析和设计

产品原型

一般在做需求分析时,往往都是对照着产品原型进行分析,因为产品原型比较直观,便于我们理解业务。

后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。

新增员工原型:

根据接口文档写:

2.代码开发

//DTO类

package com.sky.dto;
import lombok.Data;
import java.io.Serializable;

@Data
public class EmployeeDTO implements Serializable {

    private Long id;

    private String username;

    private String name;

    private String phone;

    private String sex;

    private String idNumber;

}


--------------------
//EmployeeController中创建新增员工方法

@PostMapping
@ApiOperation("新增员工")
public Result addEmp(@RequestBody EmployeeDTO dto){
    log.info("新增员工:{}", dto);
    return employeeService.addEmployee(dto);
}


-------------------
//Result类定义了后端统一返回结果格式

package com.sky.result;
import lombok.Data;
import java.io.Serializable;

/**
 * 后端统一返回结果
 * @param <T>
 */
@Data
public class Result<T> implements Serializable {

    private Integer code; //编码:1成功,0和其它数字为失败
    private String msg; //错误信息
    private T data; //数据

    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 1;
        return result;
    }

    public static <T> Result<T> success(T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.code = 1;
        return result;
    }

    public static <T> Result<T> error(String msg) {
        Result result = new Result();
        result.msg = msg;
        result.code = 0;
        return result;
    }

}


------------------
//在EmployeeService接口中声明新增员工方法

   /**
     * 新增员工
     * @param dto 员工信息
     * @return
     */
    Result addEmployee(EmployeeDTO dto);


--------------------
//在EmployeeServiceImpl中实现新增员工方法

@Override
public Result addEmployee(EmployeeDTO dto) {
    //封装实体类对象
    Employee employee = new Employee();
    //使用工具类BeanUtils把dto里的数据,拷贝到employee对象里
    BeanUtils.copyProperties(dto, employee);

    //补充数据
    //  默认密码
    employee.setPassword(DigestUtils.md5Hex(PasswordConstant.DEFAULT_PASSWORD));
    //  status状态:
    employee.setStatus(StatusConstant.ENABLE);
    //  createTime和updateTime
    LocalDateTime now = LocalDateTime.now();
    employee.setCreateTime(now);
    employee.setUpdateTime(now);
    //  createUser和updateUser:先写假数据
    employee.setCreateUser(10L);
    employee.setUpdateUser(10L);

    employeeMapper.insert(employee);

    return Result.success();
}


---------------------
//在sky-common模块com.sky.constants包下已定义StatusConstant.java

package com.sky.constant;

/**
 * 状态常量,启用或者禁用
 */
public class StatusConstant {

    //启用
    public static final Integer ENABLE = 1;

    //禁用
    public static final Integer DISABLE = 0;
}


---------------------
//在EmployeeMapper中声明insert方法

@Insert("INSERT INTO employee (name, username, password, phone, sex, id_number, status, create_time, update_time, create_user, update_user)" +
        "        VALUES (#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, #{status}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser})")
void insert(Employee employee);


--------------------
//在application.yml中已开启驼峰命名,故id_number和idNumber可对应

mybatis:
  configuration:
    #开启驼峰命名
    map-underscore-to-camel-case: true

3 功能测试

接口文档测试

请求没有携带token测试报401

启动服务:访问http://localhost:8080/doc.html,进入新增员工接口

前后端联调测试

启动nginx,访问 http://localhost

登录-->员工管理-->添加员工

添加完成之后看数据库

4 代码完善一:增加异常处理器

问题说明

描述:录入的用户名已存,抛出的异常后没有处理

分析:

新增username=zhangsan的用户,若employee表中之前已存在,数据库有设置唯一unique。

后台报错信息:

增加异常处理器

通过全局异常处理器来处理。

进入到sky-server模块,com.sky.hander包下,GlobalExceptionHandler.java添加方法

/**
     * 处理SQL异常
     * @param ex
     * @return
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        //Duplicate entry 'zhangsan' for key 'employee.idx_username'
        String message = ex.getMessage();
        if(message.contains("Duplicate entry")){
            String[] split = message.split(" ");
            String username = split[2];
            return Result.error(username + MessageConstant.ALREADY_EXISTS);
        }else{
            return Result.error(MessageConstant.UNKNOWN_ERROR);
        }
    }

5 代码完善二:绑定当前用户名

问题说明

描述:新增员工时,创建人id和修改人id设置为固定值

通过某种方式动态获取当前登录员工的id

员工登录成功后会生成JWT令牌并响应给前端:

当前用户我们从jwt令牌中获取,可以直接一个传输,在你的类中直接创建,当然不是很方便,要每个类都传,这时候有个更好的办法放线程里

ThreadLocal介绍

源码:

多次访问我们的线程不会冲突,因为每次请求就会有一个新线程,线程里的一个map空间,以this当前的对象作为键key,以set设定的值作为value

public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }

介绍:

ThreadLocal 并不是一个Thread,而是Thread的局部变量。

每个线程都有单独一份存储空间,是一个HashMap,存取数据时以ThreadLocal对象为key,以存储的值为value

这个存储空间具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

常用方法:

  • public void set(T value) 设置当前线程的线程局部变量的值

  • public T get() 返回当前线程所对应的线程局部变量的值

  • public void remove() 移除当前线程的线程局部变量

对ThreadLocal有了一定认识后,接下来继续解决问题二

(1) 准备ThreadLocal工具类

初始工程中已经封装了 ThreadLocal 操作的工具类:

在sky-common模块

package com.sky.context;

public class BaseContext {

    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    public static Long getCurrentId() {
        return threadLocal.get();
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }

}
(2) 修改拦截器代码

在拦截器中解析出当前登录员工id,并放入线程局部变量中:

在sky-server模块中,拦截器:

package com.sky.interceptor;

/**
 * jwt令牌校验的拦截器
 */
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 校验jwt
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
		//.............................
       
        //2、校验令牌
        try {
            //.................
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
            log.info("当前员工id:", empId);
            /将用户id存储到ThreadLocal
            BaseContext.setCurrentId(empId);
            
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //......................
        }
    }
}
(3) Service里获取当前用户

在Service中获取线程局部变量中的值:

小结

ThreadLocal的使用:
    作用:用于在同一线程内共享数据的
    用法:
        1. 创建ThreadLocal对象: ThreadLocal<管理的数据类型> tl = new ThreadLocal<>();
        2. 把数据绑定到当前线程上:tl.set(数据);
        3. 从当前线程上获取数据:  tl.get();
        4. 从当前线程上清理数据:  tl.remove();
    注意:
        一个ThreadLocal对象,只能管理一个数据。
            使用哪个ThreadLocal对象存储的数据,就必须用哪个ThreadLocal对象获取到这个数据
        当使用完成数据之后,一定要把数据从当前线程清理掉;否则可能会存在内存溢出的风险
    使用技巧:
        通常是创建一个类,类里提供静态的ThreadLocal对象,并提供存取数据的方法
            public class Xxxx{
                private static final ThreadLocal tl = new ThreadLocal();
                public static void setXxx(Xxx xxx){
                    tl.set(xxx);
                }
                public static Xxx getXxx(){
                    return tl.get();
                }
                public static void remove(){
                    tl.remove();
                }
            }
         如果需要绑定数据到当前线程:Xxxx.setXxx(值)
         如果需要从当前线程获取数据:Xxxx.getXxx()
         如果需要从当前线程清理数据:Xxxx.remote();

二、员工管理-分页查询

1.需求分析和设计

2 代码开发

//DTO类

package com.sky.dto;
import lombok.Data;
import java.io.Serializable;

@Data
public class EmployeePageQueryDTO implements Serializable {

    //员工姓名
    private String name;

    //页码
    private int page;

    //每页显示记录数
    private int pageSize;

}


-----------------
//后面所有的分页查询,统一都封装为PageResult对象。

package com.sky.result;

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

import java.io.Serializable;
import java.util.List;

/**
 * 封装分页查询结果
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {

    private long total; //总记录数

    private List records; //当前页数据集合

}


-----------------
//员工信息分页查询后端返回的对象类型为: Result<PageResult>

package com.sky.result;

import lombok.Data;

import java.io.Serializable;

/**
 * 后端统一返回结果
 * @param <T>
 */
@Data
public class Result<T> implements Serializable {

    private Integer code; //编码:1成功,0和其它数字为失败
    private String msg; //错误信息
    private T data; //数据

    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 1;
        return result;
    }

    public static <T> Result<T> success(T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.code = 1;
        return result;
    }

    public static <T> Result<T> error(String msg) {
        Result result = new Result();
        result.msg = msg;
        result.code = 0;
        return result;
    }

}


------------------
//在sky-server模块中,com.sky.controller.admin.EmployeeController中添加分页查询方法。

/**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("员工分页查询")
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
        log.info("员工分页查询,参数为:{}", employeePageQueryDTO);
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);//后续定义
        return Result.success(pageResult);
    }


--------------------
//在EmployeeService接口中声明pageQuery方法

/**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);


--------------------
//在EmployeeServiceImpl中实现pageQuery方法:

/**
     * 分页查询
     *
     * @param employeePageQueryDTO
     * @return
     */
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        // select * from employee limit 0,10
        //开始分页查询
        PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());

        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);//后续定义

        long total = page.getTotal();
        List<Employee> records = page.getResult();

        return new PageResult(total, records);
    }


------------------
**注意:**此处使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现。

故在pom.xml文中添加依赖(初始工程已添加)
<dependency>
   <groupId>com.github.pagehelper</groupId>
   <artifactId>pagehelper-spring-boot-starter</artifactId>
   <version>${pagehelper}</version>
</dependency>



-----------------
//在 EmployeeMapper 中声明 pageQuery 方法:


/**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);


------------------
//在 src/main/resources/mapper/EmployeeMapper.xml 中编写SQL:

<select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from employee
        <where>
            <if test="name != null and name != ''">
                and name like concat('%',#{name},'%')
            </if>
        </where>
        order by create_time desc
    </select>

3 功能测试

两种方式:

1.接口文档测试

请求没有携带token测试报401

启动服务:访问http://localhost:8080/doc.html,进入新增员工接口

2.前后端联调测试

启动nginx,访问 http://localhost

登录-->员工管理-->添加员工

 4.问题描述:操作时间字段显示有问题。

解决方式:

(1). 方式一

在属性上加上注解,对日期进行格式化

但这种方式,需要在每个时间属性上都要加上该注解,使用较麻烦,不能全局处理。

(2). 方式二(推荐 )

在WebMvcConfiguration中扩展SpringMVC的消息转换器,统一对日期类型进行格式处理

package com.sky.json;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

/**
 * 对象映射器:基于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_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    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(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);
    }
}



-------------------------
//在WebMvcConfiguration中扩展SpringMVC的消息转换器,统一对日期类型进行格式处理

/**
     * 扩展Spring MVC框架的消息转化器
     * @param converters
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器...");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转化器加入容器中
        converters.add(0,converter);
    }

三、员工管理-启用禁用

1 需求分析与设计

2 代码开发

//在sky-server模块中,根据接口设计中的请求参数形式对应的在 EmployeeController 中创建启用禁用员工账号的方法:

@PostMapping("/status/{status}")
@ApiOperation("启用/禁用员工帐号")
public Result updateStatus(@PathVariable("status") Integer status,
                           @RequestParam("id") Long empId){
    return employeeService.updateStatus(empId, status);
}


----------------
//在 EmployeeService 接口中声明启用禁用员工账号的业务方法:

 /**
     * 更新员工状态:启动/禁用
     * @param empId 员工id
     * @param status 状态
     * @return
     */
    Result updateStatus(Long empId, Integer status);


-------------------
//在 EmployeeServiceImpl 中实现启用禁用员工账号的业务方法:

@Override
public Result updateStatus(Long empId, Integer status) {
    //封装Employee对象
    Employee emp = Employee.builder().id(empId).status(status).build();
    //调用Mapper执行update语句
    employeeMapper.update(emp);
    
    return Result.success();
}


-----------------
//在 EmployeeMapper 接口中声明 update 方法:

/**
     * 根据主键动态修改属性
     * @param employee
     */
void update(Employee emp);


-------------------
//在 EmployeeMapper.xml 中编写SQL:

<update id="update">
    update employee
    <set>
        <if test="username!=null and username.length()>0">username=#{username},</if>
        <if test="name!=null and name.length()>0">name=#{name},</if>
        <if test="password!=null and password.length()>0">password=#{password},</if>
        <if test="phone!=null and phone.length()>0">phone=#{phone},</if>
        <if test="sex!=null and sex.length()>0">sex=#{sex},</if>
        <if test="status!=null">status=#{status},</if>
        <if test="updateTime!=null">update_time=#{updateTime},</if>
        <if test="createUser!=null">create_user=#{createUser},</if>
        <if test="updateUser!=null">update_user=#{updateUser},</if>
    </set>
    where id = #{id}
</update>

3 功能测试

1.接口文档测试

请求没有携带token测试报401

启动服务:访问http://localhost:8080/doc.html,进入新增员工接口

2.前后端联调测试

启动nginx,访问 http://localhost

package com.sky.json;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;

/**
 * 对象映射器:基于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_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    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(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);
    }
}



--------------------------
//在WebMvcConfiguration中扩展SpringMVC的消息转换器,统一对日期类型进行格式处理

/**
     * 扩展Spring MVC框架的消息转化器
     * @param converters
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器...");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将Java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转化器加入容器中
        converters.add(0,converter);
    }

四、员工管理-编辑员工

1 需求分析与设计

2 代码开发

//在 EmployeeController 中创建 getById 方法

	/**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据id查询员工信息")
    public Result<Employee> getById(@PathVariable Long id){
        Employee employee = employeeService.getById(id);
        return Result.success(employee);
    }


--------------
//在 EmployeeService 接口中声明 getById 方法:

 /**
     * 根据id查询员工
     * @param id
     * @return
     */
    Employee getById(Long id);


----------------
//在 EmployeeServiceImpl 中实现 getById 方法:

/**
     * 根据id查询员工
     *
     * @param id
     * @return
     */
    public Employee getById(Long id) {
        Employee employee = employeeMapper.getById(id);
        employee.setPassword("****");
        return employee;
    }


----------------
//在 EmployeeMapper 接口中声明 getById 方法:

/**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @Select("select * from employee where id = #{id}")
    Employee getById(Long id);


----------------
//在 EmployeeController 中创建 update 方法:

/**
     * 编辑员工信息
     * @param employeeDTO
     * @return
     */
    @PutMapping
    @ApiOperation("编辑员工信息")
    public Result update(@RequestBody EmployeeDTO employeeDTO){
        log.info("编辑员工信息:{}", employeeDTO);
        employeeService.update(employeeDTO);
        return Result.success();
    }


-----------------
//在 EmployeeService 接口中声明 update 方法:

/**
     * 编辑员工信息
     * @param employeeDTO
     */
    void update(EmployeeDTO employeeDTO);


-----------------
//在 EmployeeServiceImpl 中实现 update 方法:

/**
     * 编辑员工信息
     *
     * @param employeeDTO
     */
    public void update(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeDTO, employee);

        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(BaseContext.getCurrentId());

        employeeMapper.update(employee);
    }


3 功能测试

两种方式:

 1.接口文档测试

请求没有携带token测试报401

启动服务:访问http://localhost:8080/doc.html,进入新增员工接口

2.前后端联调测试

启动nginx,访问 http://localhost

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/493992.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

servlet开发详解

一、什么是servlet&#xff0c;干什么用的&#xff1f;&#xff1f;&#xff1f; tomcat作为一个web服务器&#xff0c;也称作servlet容器。servlet只有放在web服务器中才能运行&#xff0c;不能独立运行。tomcat这个容器要做三件事&#xff1a;接收请求、处理请求和响应请求。…

图形界面开发-framebuffer技术

https://www.linuxidc.com/Linux/2012-05/61024.htm 1、framebuffer 帧缓冲 帧缓冲&#xff08;framebuffer&#xff09;是Linux 系统为显示设备提供的一个接口&#xff0c;它将显示缓冲区抽象&#xff0c;屏蔽图像硬件的底层差异&#xff0c;允许上层应用程序在图形模式下直接…

SPU赋能PSI:探秘隐私集合求交核心技术与高级调度架构实践

1.SPU实现的PSI介绍 1.PSI的定义和种类 隐私集合求交&#xff08;Private Set Intersection, PSI&#xff09;是一种在密码学和安全多方计算&#xff08;MPC&#xff09;领域中的关键技术&#xff0c;允许两个或多个参与者在不泄露各自输入集合中非交集部分的前提下&#xff…

基于单片机防丢失设备的设计和实践

摘要:防止老人或者小孩走丢走失,还可以放在汽车里,利用GPS系统,设计实现了基于单片机的防丢失设备。设备利用液晶显示屏显示信息,并实时发送位置短信到手机传输当前位置的纬度和经度坐标,实现了定位与监测功能。测试结果表明,利用该设备和手机可以同时观察老人或小孩携带…

Manacher算法学习笔记(洛谷题单 Part 5.3 Manacher)

0.随便说说 字符串学的太差了&#xff0c;每次字符串算法都是学完了就忘&#xff0c;正好上场 c f d i v 1 B cfdiv1B cfdiv1B考了一个 M a n a c h e r Manacher Manacher&#xff0c;就先复习它了。 1.一些概念 子串 ( s u b s t r i n g ) (substring) (substring)&#…

【Java程序设计】【C00381】基于(JavaWeb)Springboot的爱心商城管理系统(有论文)

【C00381】基于&#xff08;JavaWeb&#xff09;Springboot的爱心商城管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#x…

外包干了4年,技术退步明显。。。。

说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入上海某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&a…

Python环境下一种新的类谱峭度算法的旋转机械故障诊断模型

谱峭度SK的本质是计算每根谱线峭度值的高阶统计量&#xff0c;谱峭度对信号中的瞬态冲击成分十分敏感&#xff0c;能有效的从含有背景噪声信号中识别瞬态冲击及其在频带中的分布。由于谱峭度的复杂性、缺少一个正式的定义和一个容易理解的计算过程使其在很长时间内都未能引入到…

Netty教程之NIO基础

NIO 介绍 NIO 全称java non-blocking IO&#xff08;非阻塞 I/O&#xff09;&#xff0c;后续提供了一系列改进的输入/输出的新特性&#xff0c;被统称为 NIO(即 New IO)&#xff0c;是同步非阻塞的。 阻塞和非阻塞是进程在访问数据的时候&#xff0c;数据是否准备就绪的一种…

光伏百科|分布式光伏电站如何开展运维管理工作?

随着经济的不断发展和生活水平的日益提高&#xff0c;节能环保已经成为全社会的责任和共识&#xff0c;分布式光伏电站作为清洁能源走进了千家万户。然而&#xff0c;在分布式光伏电站运行期间&#xff0c;面临监管困难、系统繁多、火灾隐患和运维不当等困难&#xff0c;该如何…

2024年【G2电站锅炉司炉】考试及G2电站锅炉司炉找解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 G2电站锅炉司炉考试考前必练&#xff01;安全生产模拟考试一点通每个月更新G2电站锅炉司炉找解析题目及答案&#xff01;多做几遍&#xff0c;其实通过G2电站锅炉司炉复审模拟考试很简单。 1、【多选题】下列为锅炉的…

Python爬虫之爬取网页图片

当我们想要下载网页的图片时&#xff0c;发现网页的图片太多了&#xff0c;无从下手&#xff0c;那我们写一个脚本来爬取呗。 这次的脚本是专门针对某个外国网站使用的&#xff0c;因此仅供参考思路。 在测试的过程中&#xff0c;我发现网站使用了发爬虫机制&#xff0c;具体就…

蓝桥杯-网络安全比赛(2)基础学习-正则表达式匹配电话号码、HTTP网址、IP地址、密码校验

正则表达式&#xff08;Regular Expression&#xff09;&#xff1a;定义&#xff1a;一种强大的文本处理工具&#xff0c;用于描述、匹配和查找字符串中的特定模式。应用&#xff1a;密码验证、文本搜索和替换、数据清洗等。特点&#xff1a;通过特定的元字符和规则来构建复杂…

vcf文件可以用excel打开吗?四种解决方案

vcf文件可以用excel打开吗&#xff1f; 当然可以。 一、VCF文件简介 VCF&#xff08;vCard&#xff09;文件是一种用于存储联系人信息的文件格式。它通常包含姓名、电话号码、电子邮件地址、地址等详细信息。VCF文件在多种设备和操作系统中广泛使用&#xff0c;特别是在电子邮…

2024年【G3锅炉水处理】考试题及G3锅炉水处理考试报名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 G3锅炉水处理考试题参考答案及G3锅炉水处理考试试题解析是安全生产模拟考试一点通题库老师及G3锅炉水处理操作证已考过的学员汇总&#xff0c;相对有效帮助G3锅炉水处理考试报名学员顺利通过考试。 1、【多选题】锅筒…

【八股】2024春招八股复习笔记2(大数据开发,Java)

【八股】2024春招八股复习笔记2&#xff08;大数据开发&#xff09; 文章目录 1、大数据存储&#xff08;Flume、Hive、HBase、HDFS&#xff09;2、大数据计算&#xff08;MapReduce&#xff0c;Spark、Flink&#xff09;3、大数据集群&#xff08;Yarn、ZooKeeper、kafka&…

部署云原生边缘计算平台kubeedge

文章目录 1、kubeedge架构2、基础服务提供 负载均衡器 metallb2.1、开启ipvc模式中的strictARP2.2、部署metalb2.2.1、创建IP地址池2.2.2、开启二层转发&#xff0c;实现在k8s集群节点外访问2.2.3、测试 3、部署cloudcore3.1、部署cloudcore3.2、修改cloudcore的网络类型 4、部…

二叉树|450.删除二叉搜索树中的节点

力扣题目链接 class Solution { public:TreeNode* deleteNode(TreeNode* root, int key) {if (root nullptr) return root; // 第一种情况&#xff1a;没找到删除的节点&#xff0c;遍历到空节点直接返回了if (root->val key) {// 第二种情况&#xff1a;左右孩子都为空&…

2024年第六届机器人系统与自动化工程国际会议(RSAE 2024)即将召开!

2024年第六届机器人系统与自动化工程国际会议&#xff08;RSAE 2024&#xff09;将于2024年6月21-23日在日本东京召开。RSAE 2024 的主要目标是加强合作&#xff0c;并为院士、专业人士和研究人员提供一个论坛&#xff0c;交流他们的研究成果、创新理念和解决方案&#xff0c;包…

【网络】:数据链路层

数据链路层 一.以太网帧格式二.认识MTU三.ARP协议1.ARP协议的工作流程2.ARP数据报的格式3.ARP欺骗 四.其他重要协议或技术1.DNS2.ICMP协议3.NAT技术&#xff08;重点&#xff09;4.代理服务器 五.一些问题 认识以太网 “以太网” 不是一种具体的网络, 而是一种技术标准; 既包含…