马假期的第一次

项目结构(像一个大超市的布局)

e:\javadata\Boss/
├── src/                  # 源代码目录(超市的商品区)
│   ├── main/             # 主代码(主要商品)
│   │   ├── java/         # Java源码(干货区)
│   │   │   └── cn/wolfcode/
│   │   │       ├── annotation/    # 注解(特殊标记)
│   │   │       ├── config/        # 配置(系统设置)
│   │   │       ├── controller/    # 控制器(前台接待)
│   │   │       ├── domain/        # 实体类(数据模型)
│   │   │       ├── interceptor/   # 拦截器(安检)
│   │   │       ├── mapper/        # 数据访问层(仓库管理员)
│   │   │       ├── qo/            # 查询对象(购物清单)
│   │   │       ├── service/       # 服务层(后台处理)
│   │   │       ├── util/          # 工具类(工具箱)
│   │   │       ├── vo/            # 视图对象(展示用的数据)
│   │   │       └── BossApplication.java  # 应用入口(超市大门)
│   │   └── resources/    # 资源文件(超市的装修)
│   │       ├── static/   # 静态资源(图片、CSS、JS)
│   │       ├── templates/# 模板文件(网页模板)
│   │       └── application.yml # 应用配置(超市的规章制度)

核心功能详解

1. 登录功能

登录流程

  1. 用户输入账号密码:在登录页面(login.html)输入账号和密码
  2. 点击登录按钮:触发前端的JavaScript代码
  3. 发送请求到服务器:使用Axios发送POST请求到/loginUser接口
  4. 服务器验证
    • 检查账号是否为空
    • 检查密码是否为空
    • 根据用户名查询用户信息
    • 对密码进行MD5加密(安全措施)
    • 比较加密后的密码是否一致
  5. 处理结果
    • 登录成功:把用户信息存到session中,返回成功
    • 登录失败:返回错误信息
  6. 前端处理
    • 成功:跳转到部门管理页面
    • 失败:弹出错误提示

登录代码解析

前端代码login.html):

$(".submitBtn").click(function () {
    // 发送请求到服务器
    axios.post("/loginUser", document.querySelector('#loginForm'), {
        headers: {
            'Content-Type': 'application/json'  // 告诉服务器我发的是JSON格式
        }
    }).then(function (res) {
        if (res.data.success) {
            // 登录成功,跳转到部门管理页面
            window.location.href = "/department/list";
        } else {
            // 登录失败,弹出错误提示
            alert(res.data.msg)
        }
    })
})

后端代码LoginController.java):

@RequestMapping("/loginUser")
public Result login(@RequestBody UserVo uservo, HttpSession session) {
    // 检查账号密码是否为空
    if (StringUtils.isEmpty(uservo.getUsername())) {
        return Result.fail("用户名不能为空");
    } if (StringUtils.isEmpty(uservo.getPassword())) {
        return Result.fail("密码不能为空");
    }
    try {
        // 调用service层进行登录验证
        Employee employee = employeeService.login(uservo);
        // 清空密码(安全措施,防止密码泄露)
        employee.setPassword(" ");
        // 把用户信息存到session中
        session.setAttribute("user", employee);
        // 返回登录成功
        return Result.success();
    } catch (Exception e) {
        // 登录失败,返回错误信息
        e.printStackTrace();
        return Result.fail(e.getMessage());
    }
}

密码加密EmployeeServiceImpl.java):

@Override
public Employee login(UserVo userVo) {
    // 1. 根据用户名查询用户信息
    Employee employee = employeeMapper.findByName(userVo.getUsername());
    if (StringUtils.isEmpty(employee)) {
        throw new RuntimeException("用户不存在");
    }
    // 2. 对密码进行MD5加密,然后和数据库中的密码比较
    String pass = MD5Util.encode(userVo.getPassword());
    if (!pass.equals(employee.getPassword())) {
        throw new RuntimeException("密码错误");
    }
    // 3. 返回用户信息
    return employee;
}

2. 部门管理功能(超市的部门管理)

部门管理流程

1. 查看部门列表

  1. 用户访问/department/list页面
  2. 服务器检查用户是否登录(通过拦截器)
  3. 服务器从数据库查询部门列表(带分页)
  4. 服务器把部门列表传递给模板
  5. 模板渲染出部门列表页面

2. 新增部门

  1. 点击"添加"按钮,打开模态框
  2. 填写部门名称和编码
  3. 点击"保存"按钮,发送POST请求到/department/saveOrUpdate接口
  4. 服务器检查用户是否登录
  5. 服务器保存部门信息到数据库
  6. 返回保存结果
  7. 前端处理结果,刷新页面

3. 编辑部门

  1. 点击"编辑"按钮,打开模态框,并填充部门信息
  2. 修改部门信息
  3. 点击"保存"按钮,发送POST请求到/department/saveOrUpdate接口
  4. 服务器检查用户是否登录
  5. 服务器更新部门信息到数据库
  6. 返回更新结果
  7. 前端处理结果,刷新页面

4. 删除部门

  1. 点击"删除"按钮,弹出确认框
  2. 确认后,发送GET请求到/department/delete接口
  3. 服务器检查用户是否登录
  4. 服务器从数据库删除部门
  5. 返回删除结果
  6. 前端处理结果,刷新页面

部门管理代码解析

前端代码list.ftl):

// 新增/编辑按钮点击事件
$(".btn-input").click(function () {
    // 清除模态框的数据
    $("#editForm input").val('');
    // 获取事件源绑定的数据
    var json = $(this).data("json");
    if(json){ // 编辑操作
        $("#editForm input[name=id]").val(json.id);
        $("#editForm input[name=name]").val(json.name);
        $("#editForm input[name=sn]").val(json.sn);
    }
    // 打开模态框
    $("#myModal").modal('show');
})

// 保存按钮点击事件
$(".btn-submit").click(function () {
    // 发送请求到服务器
    axios.post("/department/saveOrUpdate", document.querySelector('#editForm'), {
        headers: {
            'Content-Type': 'application/json'
        }
    }).then(handlerMessage)
})

// 删除按钮点击事件
$(".btn-delete").click(function () {
    var id = $(this).data('id');
    // 弹出确认框
    $.messager.confirm("警告","是否确认删除?",function () {
        // 发送请求到服务器
        $.get('/department/delete.do',{id:id},handlerMessage)
    })
})

后端代码DepartmentController.java):

// 查看部门列表
@GetMapping(value = "/list")
@RequireLogin  // 需要登录才能访问
public String listGet(Map<String, Object> map) {
    return getDepartmentListPage(null, map);
}

// 保存或更新部门
@PostMapping("/saveOrUpdate")
@RequireLogin  // 需要登录才能访问
@ResponseBody   // 返回JSON格式数据
public Result saveOrUpdate(@RequestBody Department department) {
    try {
        if (StringUtils.isEmpty(department.getId())) {
            // 新增部门
            departmentService.save(department);
        } else {
            // 更新部门
            departmentService.update(department);
        }
    } catch (Exception e) {
        e.printStackTrace();
        return Result.fail(e.getMessage());
    }
    return Result.success();
}

// 删除部门
@GetMapping("/delete")
@RequireLogin  // 需要登录才能访问
@ResponseBody   // 返回JSON格式数据
public Result delete(Long id) {
    try {
        departmentService.delete(id);
    } catch (Exception e) {
        e.printStackTrace();
        return Result.fail(e.getMessage());
    }
    return Result.success();
}

3. 登录验证机制(安检系统)

工作原理

  1. 定义注解:创建一个@RequireLogin注解,标记在需要登录才能访问的方法上
  2. 配置拦截器:创建一个拦截器,拦截所有请求
  3. 拦截器检查:拦截器检查请求的方法是否有@RequireLogin注解
  4. 登录验证:如果有注解,检查session中是否有用户信息
  5. 处理未登录:如果没有用户信息,返回"请先登录"的错误信息

代码解析

注解定义RequireLogin.java):

@Target({ElementType.METHOD})  // 只能用在方法上
@Retention(RetentionPolicy.RUNTIME)  // 运行时有效
@Documented
public @interface RequireLogin {
    boolean required() default true;  // 默认需要登录
}

拦截器实现WebHandlerInterceptor.java):

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 检查是否是controller方法
    if (!(handler instanceof HandlerMethod)) {
        return true;  // 不是controller方法,放行
    }
    // 获取方法
    HandlerMethod method = (HandlerMethod) handler;
    // 获取方法上的注解
    RequireLogin requireLogin = method.getMethodAnnotation(RequireLogin.class);
    // 检查是否需要登录
    if (StringUtils.isEmpty(requireLogin) || !requireLogin.required()) {
        return true;  // 不需要登录,放行
    }
    // 检查session中是否有用户信息
    Employee user = (Employee) request.getSession().getAttribute("user");
    if (StringUtils.isEmpty(user)) {
        // 没有用户信息,返回错误
        response.setContentType("text/html;charset=utf-8");
        Result result = Result.fail("请先登录");
        response.getWriter().write(JSON.toJSONString(result));
        response.getWriter().flush();
        response.getWriter().close();
        return false;  // 不放行
    }
    // 有用户信息,放行
    return true;
}

核心实体类(数据模型)

1. Department

  • id: 部门ID(就像部门的编号)
  • name: 部门名称(就像部门的名字)
  • sn: 部门编码(就像部门的简写)

2. Employee

  • id: 员工ID
  • name: 员工姓名
  • password: 密码
  • email: 邮箱)
  • age: 年龄
  • admin: 是否管理员)
  • deptId: 所属部门ID

常见问题及解决方案

1. 登录失败

  • 原因:账号不存在或密码错误
  • 解决:检查账号密码是否正确,确保数据库中有对应的用户信息

2. 无法访问部门管理页面

  • 原因:用户未登录或登录已过期
  • 解决:重新登录系统

3. 保存部门失败

  • 原因:部门名称或编码为空,或数据库操作失败
  • 解决:填写完整的部门信息,检查数据库连接是否正常

4. 删除部门失败

  • 原因:部门不存在,或部门下有员工
  • 解决:确保部门存在,且部门下没有员工

总结

  • Spring Boot项目的搭建和配置
  • 三层架构的设计和实现
  • 前后端分离的开发模式
  • 登录验证机制的实现
  • 数据库操作的基本方法
  • 网页开发的基本技能
posted @ 2026-02-23 23:12  诺森德的雪原  阅读(5)  评论(0)    收藏  举报