文章目录
前言
为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)
一、后台登录功能开发
1. 需求分析
1. 页面原型展示
2. 登录页面展示
3. 查看登录请求信息
- 通过浏览器调试工具 (F12),可以发现,点击登录按钮时,页面会发送请求 (请求地址为http://localhost:8080/employee/login)并提交参数 (username和password)
- 此时报404,是因为我们的后台系统还没有响应此请求的处理器,所以我们需要创建相关类来处理登录请求
4. 数据模型(employee表)
employee表存储管理员工的信息,对比员工的用户名密码进行登录操作
2. 代码开发
1. 创建实体类包entity,并创建实体类Employee,和employee表进行映射
/**
* 员工实体
*/
@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、Service、Mapper
- Mapper
@Mapper
public interface EmployeeMapper extends BaseMapper<Employee>{
}
- Service
Service接口
public interface EmployeeService extends IService<Employee> {
}
ServiceImpl
@Service
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper,Employee> implements EmployeeService{
}
- Controller
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
}
3. 创建返回结果类(前后端约定)
- 前端页面处理数据模型分析
- 后端数据模型设计示例
/**
* 通用返回结果,服务端响应的数据最终都会封装成此对象
* @param <T>
*/
@Data
public class R<T> {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
//登录成功,返回code = 1,并返回数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
//登录失败,返回code = 0,并返回错误信息msg
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
此类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回给前端页面
4. 在controller中创建登录方法
处理逻辑如下:
- 将页面提交的密码password进行md5加密处理
- 根据页面提交的用户名username查询数据库
- 如果没有查询到则返回登录失败结果
- 密码比对,如果不一致则返回登录失败结果
- 查看员工状态,如果为已禁用状态(锁定字段status,1为正常,0为锁定),则返回员工已禁用结果
- 登录成功,将员工id存入Session并返回登录成功结果
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
/**
* 员工登录
* @param request
* @param employee
* @return
*/
@PostMapping("/login")
//@RequestBody:封装json数据
//登录成功后员工的id存放在session中,通过request对象可以获取session,进一步获取用户信息
public R<Employee> login(HttpServletRequest request,@RequestBody Employee employee){
//1、将页面提交的密码password进行md5加密处理
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
//2、根据页面提交的用户名username查询数据库
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
//等值条件查询
queryWrapper.eq(Employee::getUsername,employee.getUsername());
//由于在设计表的时候用户名字段索引类型设置为了Unique,查出来的是唯一对象,所以此处调用的是getOne方法
Employee emp = employeeService.getOne(queryWrapper);
//3、如果没有查询到则返回登录失败结果
if(emp == null){
return R.error("登录失败");
}
//4、密码比对,如果不一致则返回登录失败结果
if(!emp.getPassword().equals(password)){
return R.error("登录失败");
}
//5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果
if(emp.getStatus() == 0){
return R.error("账号已禁用");
}
//6、登录成功,将员工id存入Session并返回登录成功结果
request.getSession().setAttribute("employee",emp.getId());
return R.success(emp);
}
}
3. 功能测试(简略)
- 运行启动类及项目结构示例
- 在浏览器访问登录页面,输入用户名admin和密码123456
- 点击登录
- 后端页面渲染浅析
二、后台退出功能开发
1. 需求分析
-
员工登录成功后,页面跳转到后台系统首页面(backend/index.html),此时会显示当前登录用户的姓名
-
如果员工需要退出系统,直接点击右侧的退出按钮即可退出系统,退出系统后页面应跳转回登录页面
2. 代码开发
用户点击页面中退出按钮,发送请求,请求地址为/employee/logout,请求方式为POST.我们只需要在Controller中创建对应的处理方法即可,具体的处理逻辑:
- 清理Session中的用户id
- 返回结果
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
/**
* 员工退出
* @param request
* @return
*/
@PostMapping("/logout")
public R<String> logout(HttpServletRequest request){
//清理Session中保存的当前登录员工的id
request.getSession().removeAttribute("employee");
return R.success("退出成功");
}
}
3. 功能测试(简略)
先登录,再点击退出
三、登录页面功能完善
1. 问题分析
- 前面我们已经完成了后台系统的员工登录功能开发,但是还存在一个问题:用户如果不登录,直接访问系统首页面,照样可以正常访问。
- 这种设计并不合理,我们希望看到的效果应该是,只有登录成功后才可以访问系统中的页面,如果没有登录则跳转到登录页面。
- 那么,具体应该怎么实现呢?
答案就是使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面。
2. 代码实现
1. 实现步骤
- 创建自定义过滤器LoginCheckFilter
- 在启动类上加入注解@ServletComponentScan
- 完善过滤器的处理逻辑
2. 过滤器处理逻辑
- 获取本次请求的URI
- 判断本次请求是否需要处理
- 如果不需要处理,则直接放行
- 判断登录状态,如果已登录,则直接放行
- 如果未登录则返回未登录结果
3. 结合前端相关js文件进行代码编写
- 前端js处理逻辑分析
- 创建filter包,并创建编写过滤器类LoginCheckFilter
/**
* 检查用户是否已经完成登录
*/
//名称+拦截路径
@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/**"
};
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3、如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",requestURI);
// 放行
filterChain.doFilter(request,response);
return;
}
//4、判断登录状态,如果已登录,则直接放行
// 从session中取出用户,能取出来不为空则为登录
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){
// 是否匹配到url中的数组元素,能则放行
for (String url : urls) {
// match:匹配方法
boolean match = PATH_MATCHER.match(url, requestURI);
if(match){
return true;
}
}
return false;
}
}
- 在启动类上添加**@ServletComponentScan**注解
...
@ServletComponentScan
public class ReggieApplication {
...
}
3. 功能测试(简略)
1. 运行启动类ReggieApplication及代码文件结构参考
2. 不登录直接访问后台首页
我们发现页面跳转回了登录页面
3. 再次查看控制台
总结
欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/156718.html