瑞吉外卖 02 CRUD员工

完善登录功能

问题

因为可以没有登录就直接跳转到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("没有查询到对应员工信息!");
    }

猜你喜欢

转载自blog.csdn.net/weixin_46066669/article/details/131387232