1.创建过滤器步骤:
2.具体实现:
首先在ReggieApplication.java类中添加ServletComponentScan注解:
接着创建filter包,在包中创建LoginCheckFilter类:
LoginCheckFilter类的代码如下:
package com.mj.reggie.filter;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author mj
* @version 1.0
* 检查用户是否已经完成登录
*/
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("拦截到请求: {}", httpServletRequest.getRequestURI());
filterChain.doFilter(httpServletRequest,response);
}
}
1.过滤器具体的处理逻辑图:
2.在LoginCheckFilter类中完善过滤器具体的处理逻辑,代码如下:
package com.mj.reggie.filter;
import com.alibaba.fastjson.JSON;
import com.mj.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author mj
* @version 1.0
* 检查用户是否已经完成登录
*/
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
@Slf4j
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 httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 1.获取本次请求的URI
String requestURI = httpServletRequest.getRequestURI();
log.info("拦截到请求:{}", requestURI);
// 定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
// 2.判断本次请求是否需要处理
boolean check = check(urls, requestURI);
// 3.如果不需要处理,则直接放行
if (check) {
log.info("本次请求{}不需要处理", requestURI);
filterChain.doFilter(httpServletRequest, response);
return;
}
// 4.判断登录状态,如果已登录,则直接放行
if (httpServletRequest.getSession().getAttribute("employee") != null) {
log.info("用户已登录,用户ID为:{}", httpServletRequest.getSession().getAttribute("employee"));
filterChain.doFilter(httpServletRequest, response);
return;
}
log.info("用户未登录");
// 5.如果未登录则返回未登录结果,通过输出流方式向页面返回响应数据
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
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;
}
}
在EmployeeController类中编写save方法实现新增员工功能,代码如下:
/*
* 新增员工
* */
@PostMapping
public R<String> 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
Long empId = (Long) request.getSession().getAttribute("employee");
employee.setCreateUser(empId);
employee.setUpdateUser(empId);
employeeService.save(employee);
return R.success("新增员工成功");
}
}
## 2.读入数据
代码如下(示例):
```c
data = pd.read_csv(
'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())
在com.mj.reggie.common包中新建一个GlobalExceptionHandler类作为全局异常处理器类:
代码如下:
package com.mj.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 mj
* @version 1.0
* 全局异常处理
*/
@ControllerAdvice(annotations = {RestController.class, Controller.class})
@Slf4j
@ResponseBody
public class GlobalExceptionHandler {
@ExceptionHandler(SQLIntegrityConstraintViolationException.class)
public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex) {
log.info(ex.getMessage());
if (ex.getMessage().contains("Duplicate entry")) {
String[] strings = ex.getMessage().split(" ");
String msg = strings[2] + "已存在";
return R.error(msg);
}
return R.error("未知错误");
}
}
1.在实现功能之前,我们需要先配置mybatisplus的分页插件,在com.mj.reggie.config包中创建一个MybatisPlusConfig类:
代码如下:
package com.mj.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;
/**
* @author mj
* @version 1.0
* 配置MP的分页插件
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
2.在EmployeeController类中创建page方法实现员工信息分页查询功能,代码如下:
/*
* 员工信息分页查询
* */
@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> lambdaQueryWrapper = new LambdaQueryWrapper();
// 添加过滤条件
lambdaQueryWrapper.like(StringUtils.isNotEmpty(name), Employee::getName, name);
// 添加排序条件
lambdaQueryWrapper.orderByDesc(Employee::getUpdateTime);
// 执行查询
employeeService.page(pageInfo, lambdaQueryWrapper);
return R.success(pageInfo);
}
}
页面中的ajax请求发送流程如下:
在EmployeeController类中创建update方法实现根据员工ID修改员工信息功能,代码如下:
/*
* 根据ID修改员工信息
* */
@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("员工信息修改成功");
}
原因是js对long型数据进行处理时丢失精度,导致提交的id和数据库中的id不一致。
而想要解决这个问题,就需要我们将long型数据统一转换成String字符串,具体操作如下:
先将资料中提供的对象转化器类JacksonObjectMapper拷贝到com/mj/reggie/common包中:
然后在WebMvcConfig类中创建extendMessageConverters方法以扩展MVC框架的消息转换器,代码如下:
/*
* 扩展MVC框架的消息转换器
* */
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
// 设置对象转换器,底层使用Jackson将Java对象转为json
messageConverter.setObjectMapper(new JacksonObjectMapper());
// 将上面的消息转换器对象追加到mvc框架的转换器集合中
converters.add(0, messageConverter);
}
}
为了让用户信息回显到编辑页面:
我们需要编写getById方法来查询员工信息并返回,代码如下:
/*
* 根据id查询员工信息
* */
@GetMapping("/{id}") // 接收URL地址上的参数Id用 /{id} 写法
// @PathVariable 是路径变量,表示id这个参数在请求路径里
public R<Employee> getById(@PathVariable Long id) {
log.info("根据id查询员工信息...");
// 根据id查询员工信息并通过employee对象返回
Employee employee = employeeService.getById(id);
if (employee != null){
return R.success(employee);
}
return R.error("没有查询到对应员工信息");
}
}
返回之后修改员工信息时所使用的方法就是我们之前写好的update方法。