登录功能
需求分析
1. Controller
- 定义:Controller是MVC(Model-View-Controller)设计模式中的一部分,负责处理HTTP请求并返回HTTP响应。在Spring MVC中,Controller通常是一个处理特定HTTP请求的类。
- 作用:
- 接收前端发送的请求,包括请求参数。
- 调用Service层处理业务逻辑。
- 将处理结果返回给前端,可以是HTML页面、JSON数据等格式。
- 与其他组件的关系:Controller层调用Service层的方法来处理业务逻辑,但不直接操作数据库。
2. Service
- 定义:Service层位于Controller和Data Access层(如Mapper)之间,负责处理业务逻辑。
- 作用:
- 实现业务逻辑,可能涉及多个数据访问操作(如CRUD操作)的组合和转换。
- 封装复杂的业务逻辑,以便Controller层调用。
- 与其他组件的关系:
- Service层调用Mapper层(或DAO层)的方法来实现数据访问。
- 被Controller层调用以处理业务逻辑。
3. ServiceImpl
- 定义:ServiceImpl是Service接口的实现类。在Java中,通常会将Service层设计为一个接口,然后提供一个或多个实现类。
- 作用:
- 实现Service接口中定义的业务逻辑方法。
- 调用Mapper层的方法来完成具体的数据访问操作。
- 与其他组件的关系:
- 实现Service接口,为Controller层提供具体的业务逻辑实现。
- 调用Mapper层进行数据库操作。
4. Mapper(DAO)
- 定义:Mapper(有时也被称为DAO,即Data Access Object)是数据访问层的一部分,负责将数据库中的数据映射到Java对象,并将Java对象保存到数据库中。
- 作用:
- 定义对数据库进行CRUD操作的方法。
- 提供数据访问的接口给Service层调用。
- 与其他组件的关系:
- Mapper层直接与数据库交互,执行SQL语句来查询、插入、更新或删除数据。
- 被Service层调用以执行数据访问操作。
5. DB(数据库)
- 定义:DB是数据库(Database)的缩写,它存储和管理着应用程序所需的数据。
- 作用:
- 存储应用程序的数据。
- 提供数据查询、插入、更新和删除的功能。
- 与其他组件的关系:
- 数据库是Mapper层(或DAO层)的直接交互对象。
- Mapper层通过执行SQL语句与数据库进行交互,完成数据的增删改查操作。
功能代码开发
1.创建实体类与数据库表进行映射
例如 在entity包Employee包
package com.itheima.riggie.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String name;
private String password;
private String phone;
private String sex;
private String idNumber;
private Integer status;
private LocalDateTime createTime;
private LocalDateTime updateTime;
@TableField(fill = FieldFill.INSERT)
private Long createUser;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;
}
2.创建对应的controller、severe、serviceimpl、mapper
在controller包下创建EmployeeController
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee) {
return null;
}
}
在service创建对应的EmployeeService
package com.itheima.riggie.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.riggie.entity.Employee;
public interface EmployeeService extends IService<Employee> {
}
在service下的impl包 创建service的实现方法 EmployeeServiceImpl
package com.itheima.riggie.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.riggie.entity.Employee;
import com.itheima.riggie.mapper.EmployeeMapper;
import com.itheima.riggie.service.EmployeeService;
import org.springframework.stereotype.Service;
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper,Employee> implements EmployeeService {
}
在mapper包下创建EmployeeService
package com.itheima.riggie.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.riggie.entity.Employee;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EmployeeMapper extends BaseMapper<Employee> {
}
设置通用的返回
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
LambdaQueryWrapper<Employee> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Employee::getUsername, employee.getUsername());
Employee emp = employeeService.getOne(wrapper);
if (emp == null) {
return R.error("用户名或密码错误");
}
if (!emp.getPassword().equals(password)) {
return R.error("登录失败");
}
if (emp.getStatus() == 0) {
return R.error("账号已被禁用");
}
request.getSession().setAttribute("employee", emp.getId());
return R.success(emp);
退出登录
/**
* 员工退出
*/
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request) {
request.getSession().removeAttribute("employee");
return R.success("退出成功");
完善登录功能
问题分析
前面已经完成了后台系统的员工登录功能开发,但是还存在一个问题
用户如果不登录,直接访问系统首页面,照样可以正常访问
这种设计并不合理,我们希望看到的效果应该是,只有登录成功后才可以访问系统中的页面,如果没有登录则跳转到登录页面。
使用拦截器或过滤器
代码实现,实现步骤:
1、创建自定义过滤器LoginCheckFilter
2、在启动类上加入注解@ServletComponentScan
3、完善过滤器的处理逻辑
代码实现
package com.itheima.riggie.filter;
import com.alibaba.fastjson.JSON;
import com.itheima.riggie.common.R;
import lombok.extern.slf4j.Slf4j;
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;
/**
* 检查用户是否已经完成登录
*/
@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 request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、获取本次请求的URI
String requestURI = request.getRequestURI();// /backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/common/**"
};
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3、如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
//4、判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
filterChain.doFilter(request,response);
return;
}
log.info("用户未登录");
//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;
}
}