02 CRUD 员工

本贴最后更新于 515 天前,其中的信息可能已经时移世易

完善登录功能

问题

因为可以没有登录就直接跳转到 index 页面,所以我们必须要增加一个拦截器或者过滤器,在过滤器中判断用户是否已经完成登录,只有登录成功后才可以访问系统中的页面。

代码实现

​​image​​

  1. 先在 reggie 下创建一个 filter 包,新建一个 LoginCheckFilter 类:

    1.  package com.itheima.reggie.filter;
      
       import lombok.extern.slf4j.Slf4j;
       import org.springframework.stereotype.Component;
       import org.springframework.web.bind.annotation.RequestBody;
      
       import javax.servlet.*;
       import javax.servlet.annotation.WebFilter;
       import javax.servlet.http.HttpServletRequest;
       import javax.servlet.http.HttpServletResponse;
       import java.io.IOException;
      
       /**
        * @author 检查用户是否已经完成登录
        * @create 2023-06-24 11:10
        */
       //slf4j是用来输出日志
       @Slf4j
       @WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
       public class LoginCheckFilter implements Filter{
           @Override
           public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
               HttpServletRequest request = (HttpServletRequest) servletRequest;
               HttpServletResponse response = (HttpServletResponse) servletResponse;
               log.info("拦截到请求:{}", request.getRequestURI());
               filterChain.doFilter(request,response);
           }
       }
      
  2. 在启动类下加 @ServletComponentScan​注解。

  3. 过滤器的代码实现:

    1. 处理逻辑:image

      因为在前端页面中引入了一个 js 文件,使用了一个前端的响应拦截器,功能是在后台返回的数据当中如果这个用户没有登录则自动跳转到登录界面,因此后台只要返回一个数据就好了。

      imageimage​​

    2. 实现代码:

      package com.itheima.reggie.filter;
      
      import com.alibaba.fastjson.JSON;
      import com.itheima.reggie.common.R;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.stereotype.Component;
      import org.springframework.util.AntPathMatcher;
      import org.springframework.web.bind.annotation.RequestBody;
      
      import javax.servlet.*;
      import javax.servlet.annotation.WebFilter;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import java.io.IOException;
      
      /**
       * @author 检查用户是否已经完成登录
       * @create 2023-06-24 11:10
       */
      //slf4j是用来输出日志
      @Slf4j
      @WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
      public class LoginCheckFilter implements Filter{
          //路径匹配器,支持通配符
          public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
      
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              HttpServletRequest request = (HttpServletRequest) servletRequest;
              HttpServletResponse response = (HttpServletResponse) servletResponse;
      
              //1.获取本次请求的URL
              String requestURL = request.getRequestURI();
      
              //定义不需要处理的请求路径
              String[] urls = new String[]{
                      "/employee/login",
                      "/employee/logout",
                      "/backend/**",
                      "/front/**"
              };
      
              //2.判断本次请求是否需要处理
              boolean check=check(urls,requestURL);
      
              //3.如果不需要处理,则直接放行
              if(check){
                  filterChain.doFilter(request,response);
                  return;//就不需要直接后续的代码了
              }
      
              //4.判断登陆状态,如果已登录,则直接放行
              if(request.getSession().getAttribute("employee")!=null){
                  filterChain.doFilter(request,response);
                  return;
              }
      
              //5.如果未登录则返回未登录结果
              //给前端一个数据,由前端跳转
              response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
              return;
          }
      
          /**
           * 路径匹配,检查本次请求是否需要放行
           * @param urls
           * @param requestURI
           * @return
           */
          public boolean check(String[] urls,String requestURI){
              for(String url : urls){
                  boolean match = PATH_MATCHER.match(url,requestURI);
                  if(match){
                      return true;
                  }
              }
              return false;//说明匹配不上
          }
      }
      

新增员工

预准备

需求分析

image

通过前端的表单保存到 employee 这张表当中去,用户状态正常是 1,禁用是 0。

image

image

image

程序执行流程

image

前端增加员工的点击按钮事件:image

image

image​​

代码实现

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;

/**
 * @author 全局异常处理
 * @create 2023-06-24 22:21
 */
//只要加了这两个注解都会被这个处理器处理,最后还要封装成数据
@ControllerAdvice(annotations={RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 异常处理方法
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error(ex.getMessage());
        if(ex.getMessage().contains("Duplicate entry")){
            String[] split=ex.getMessage().split(" ");//按空格分割
            String msg=split[2]+"已存在";//提示用户名已经存在
            return R.error(msg);//会在前端有个提示框
        }
        return R.error("未知错误");//会在前端有个提示框
    }
}

捕获异常

image

在 common 下创建一个 GlobalExceptionHandler​类,编写代码:

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;

/**
 * @author 全局异常处理
 * @create 2023-06-24 22:21
 */
//只要加了这两个注解都会被这个处理器处理,最后还要封装成数据
@ControllerAdvice(annotations={RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 异常处理方法
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error(ex.getMessage());
        return R.error("失败了");//会在前端有个提示框
    }
}

员工信息分页查询

预准备

​​image​​

image

前端代码:

request.js 拦截器将数据组装了,方便传参。因为前端的数据是 res.data.records,因此我们后端也要符合数据格式,这和 mybatis 的 page 类一样。page 默认是 1,pagesize 默认是 10.

image

image

image

上下翻页也会改变事件:

image

前端的状态数据展示:

image

代码开发

在 config 下创建一个 MybatisPlusConfig 类,编写代码:

package com.itheima.reggie.common;

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;

/**
 * @author 配置MP的分页插件
 * @create 2023-06-25 15:05
 */
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

在 controller 下编写:

 /**
     * 员工信息分页查询,因为前端发送的是get请求,所以用getmapping。
     * @param page
     * @param pageSize
     * @param name 可能会传,可能会没有数值。
     * @return
     */
    @GetMapping("/page")
    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.isEmpty(name),Employee::getName,name);
        //添加排序条件:按照更新日期降序排列
        queryWrapper.orderByDesc(Employee::getUpdateTime);

        //执行查询
        employeeService.page(pageInfo,queryWrapper);
        return R.success(pageInfo);
    }

启用/禁用员工账号

预准备

image

image

image

前端代码

image

从 storage 拿到用户名,判断 username 是不是管理员,显示禁用按钮。scope.row 就是这一条数据所封装的数据对象,点击事件会触发 statusHandle 并传 scope.row 这个对象。

image

image

ajax 发送请求:

image

执行流程

image

image

image

问题

image

js 在处理数据的时候丢失了精度。​image

解决方案:

image

将资料中的对象映射器复制到 common 包下,再补充 @Configuration 注解,否则后面会网页打不开。

代码开发

controller 下:

    /**
     * 根据id修改员工信息,因为传的是请求体,所以要加注解
     * @param employee
     * @return
     */
    @PutMapping
    public R<String> update(HttpServletRequest request,@RequestBody Employee employee){
        log.info(employee.toString());
        Long empId=(Long)request.getSession().getAttribute("employee");
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(empId);
        employeeService.updateById(employee);
        return R.success("员工信息修改成功");
    }

没在 putmapping 会报 405 错误!

在 WebMvcConfig 下:

    /**
     * 扩展MVC框架的消息转换器,将controller的返回数据R结果类转换成json数据
     * @param converters
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter=new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息转换器对象追加到mvc框架的转换器集合当中,放在0优先使用
        converters.add(0,messageConverter);
        super.extendMessageConverters(converters);

    }

编辑员工信息

预准备

image

​​image

前端代码

actiontype 说明这个页面既可以当做编辑页面也可以当做增加页面。

image

进行字符串处理,从?后面截取传的参数,如果能找到”id=“,就说明有这个参数,然后把”id=“这个字符串删除,只留下了 id 数值。

image

发送请求,回显数据,因为男女是单选按钮,就处理成单选按钮的 id(0 和 1)。

image

image

image

代码实现

    /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    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("没有查询到对应员工信息!");
    }
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...