1.新员工2-51.1需求分析2-5
员工信息可以在后台系统中管理,后台系统用户可以通过新员工添加,点击【添加员工】按钮转到新页面如下:
新员工实际上是在employee表中插入我们新页面输入的员工数据。需要注意的是,employee表中对username字段增加了唯一的约束,因为username是员工的登录账户,必须是唯一的
1.2代码开发2-6在开发代码之前,需要梳理整个程序的执行过程:
1、页面发送ajax请求,以json的形式向服务端提交新员工页面输入的数据
2、服务器Controler接收页面提交的数据,并调用Service保存数据
3、Service调用Mapper操作数据库,保存数据
Employeronerleler这里解释@PostMaping后面为什么不加路径,因为点击添加按钮后发起的路径是
http://localhost:8080/employee,这个employee,我们在employecontroler类中添加了
@RequestMapping("/employee“)注释,会自动添加employee
//保存员工信息 2-7 @PostMapping public R save(HttpServletRequest request,@RequestBody Employee employee){ log.info(新员工,员工信息:{}employee.toString()); //设置初始密码123456,MD5加密处理需要进行 employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes())); employee.setCreateTime(LocalDateTime.now()); employee.setUpdateTime(LocalDateTime.now()); //获得当前登录用户的id,这个id是管理员的id,因为只有管理员增加了员工的右权限 Long empId = (Long) request.getSession().getAttribute("employee"); employee.setCreateUser(empId); employee.setUpdateUser(empId); employeeService.save(employee); return R.success(“新员工成功”); }
测试
1.3解决员工同名异常问题2-8前面的程序还有一个问题,就是当我们在新员工中输入的账号已经存在时,由于employee表中对字段的唯一约束,此时程序会抛出异常:
1.3.1解决方法2-8此时,我们的程序需要异常捕获,通常有两种处理方法:
1、在Controller方法中添加try、异常捕获catch 2、使用异常处理器捕获2-82-9Globalexceptiondler
package com.itheima.reggie.common;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import java.sql.SQLIntegrityConstraintViolationException;/** * 全局异常处理 2-8 *////@ContrlerAdvice注释的作用是拦截,例如,拦截添加了Restcontroler注释和controler注释的类别@ControllerAdvice(annotations = {RestController.class, Controller.class})@ResponseBody///返回结果封装成json@slf4jpublic class GlobalExceptionHandler { /** * 异常处理方法2-8 * @return */ //处理SQLIntegrityconstraintiontionexception异常 @ExceptionHandler(SQLIntegrityConstraintViolationException.class) public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){ log.error(ex.getMessage()); //2-9 if(ex.getMessage().contains("Duplicate entry")){ String[] split = ex.getMessage().split(" "); String msg = split[2] + "已存在"; return R.error(msg); } return R.error(“未知错误”); }}
2.阶段总结2-10 3.员工信息分页查询2-113.1需求分析2-111
很多时候,系统中的员工如果在一个页面上全部显示,会显得凌乱,不方便查看,所以列表数据会在一般系统中以分页的形式显示。
3.2代码开发2-12在开发代码之前,需要梳理整个程序的执行过程:
1、页面发送ajax请求,分页查询参数(page.pageSize、name)提交到服务端
2、服务器Controler接收页面提交的数据,并调用Service查询数据
3、Service调用Mapper操作数据库,查询分页数据
4、Controller将查询到的分页数据响应到页面
5、页面接收分页数据,并通过elementultable组件显示到页面上
MybatisPlusConfigggig代码实现2-13配置MP的分页插件
package com.itheima.reggie.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;/** * 配备MP的分页插件 2-13 */@Configurationpublic class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return mybatisPlusInterceptor; }}
接口设计
前端注意事项
Employecontroler2-132-14
////员工信息分页查询 2-13 2-14 @GetMapping("/page") public R<Page> page(int page,int pageSize,String name){//page第几页,pagesize查询了几个条目 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); return R.success(pageInfo); }
4.禁用员工账号2-17
只不过是修改status,0禁用,1启用
4.1需求分析在员工管理列表页面上,可以启用或禁止员工账户。禁用账户的员工不能登录系统,启用后的员工可以正常登录。
需要注意的是,只有管理员(admin用户)才能启用和禁止其他普通用户,因此不显示普通用户登录系统后的启用和禁用按钮。
4.2代码开发2-19 开发流程2-20在开发代码之前,需要梳理整个程序的执行过程:
1、页面发送ajax请求,将参数发送到页面(id、status)提交到服务端
2、服务器Controler接收页面提交的数据,并调用Service更新数据
3、Service调用Maper操作数据库
启用和禁用员工账户本质上是一种更新操作,即操作status状态字段,在controller中创建update方法。这种方法是修改员工信息的通用方法
Employecontroler2-2000
////根据id修改员工信息 2-20 //启用禁用员工 2-20 @PutMapping public R<String> update(HttpServletRequest request,@RequestBody Employee employee){ log.info(employee.toString()); ///从session中取出更新人的iddon Long empId = (Long) request.getSession().getAttribute("employee"); employee.setUpdateTime(LocalDateTime.now());///更新时间 employee.setUpdateUser(empId);///更新人id employeeService.updateById(employee); return R.success(成功修改员工信息); }
结果数据库没有成功更新
代码修复2-21我们已经发现了问题的原因,即js在处理long数据时失去了精度,导致提交的id与数据库中的id不一致。(js只能保证前16位的准确性,但我们的id是19位)
如何解决这个问题?
当服务端响应json数据时,我们可以处理long数据,将long数据统一转换为string字符串如下:
具体实现步骤:2-211)为JacksonobjectMaper提供对象转换器,基于Jackson转换Java对象到Json数据(已在数据中提供,直接复制到项目中使用)
2)在WebMvcconfig配置类中扩展Springmvc的消息转换器,使用提供的对象转换器转换Java对象到Json数据
Jacksonjectmapper2-21
package com.itheima.reggie.common;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.module.SimpleModule;import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;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.math.BigInteger;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对象 2-21 * 将JSON分析为Java对象的过程称为 [Java对象从JSON反序列化] * JSON是从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_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); }}
修改WebMvconfig配置类2-21
/** * 扩展MVC框架的消息转换器 2-21 * @param converters */ @Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { log.info(”扩展新闻转换器..."); ////创建信息转换器对象 MapingJacksonHttpMessageConverter messageConverter = new MapingJacksonHttpMessageConverter(); //设置对象转换器(设置为我们自己的信息转换器),Jackson将Java对象转化为json messageConverter.setObjectMapper(new JacksonObjectMapper()); ///将上述信息转换器对象添加到MVC框架的转换器集合中 ///这里这个0 索引的目的是把我们的信息转换器放在集合的前面,优先使用 converters.add(0,messageConverter); }
测试成功
5.编辑员工信息2-2335.1需求分析2-23 5.2代码开发2-23在开发代码之前,需要对操作过程和相应程序的执行过程进行梳理:
1、点击编辑按钮时,页面跳转到add.html,并在url中携带参数[员IID]
2、在add.url中的参数[员IID]在html页面上获取
3、发送ajax请求,请求服务端,并提交员工id参数
4、服务端接收请求,根据员工ID查询员工信息,以json的形式响应员工信息
5、页面接收服务端响应的json数据,并通过VUE数据绑定显示员工信息
6、点击保存按钮,发送ajax请求,以json的形式向服务端提交页面中的员工信息
7、服务端接收员工信息并处理,完成后响应页面
8、页面在收到服务端响应信息后进行相应处理
注意:add.html页面是公共页面,新员工和编辑员工都在这个页面上操作
显然,这是一条restful风格的路径,需要使用@Pathvariable来获取路径中的值
编辑员工信息Employecontroller2-25
/** * 根据id查询员工信息 * @param id * @return */ @GetMapping("/{id})//restful风格 public R<Employee> getById(@PathVariable Long id){ log.info(”根据id查询员工信息..."); Employee employee = employeeService.getById(id); if(employee != null){ return R.success(employee); } return R.error(未查询相应员工信息); }
修改名称并保存(以下是保存的实用方法和方法启用禁用那里的代码是一个,本质上是修改的)