马假期的第一次
项目结构(像一个大超市的布局)
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. 登录功能
登录流程
- 用户输入账号密码:在登录页面(
login.html)输入账号和密码 - 点击登录按钮:触发前端的JavaScript代码
- 发送请求到服务器:使用Axios发送POST请求到
/loginUser接口 - 服务器验证:
- 检查账号是否为空
- 检查密码是否为空
- 根据用户名查询用户信息
- 对密码进行MD5加密(安全措施)
- 比较加密后的密码是否一致
- 处理结果:
- 登录成功:把用户信息存到session中,返回成功
- 登录失败:返回错误信息
- 前端处理:
- 成功:跳转到部门管理页面
- 失败:弹出错误提示
登录代码解析
前端代码(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. 查看部门列表
- 用户访问
/department/list页面 - 服务器检查用户是否登录(通过拦截器)
- 服务器从数据库查询部门列表(带分页)
- 服务器把部门列表传递给模板
- 模板渲染出部门列表页面
2. 新增部门
- 点击"添加"按钮,打开模态框
- 填写部门名称和编码
- 点击"保存"按钮,发送POST请求到
/department/saveOrUpdate接口 - 服务器检查用户是否登录
- 服务器保存部门信息到数据库
- 返回保存结果
- 前端处理结果,刷新页面
3. 编辑部门
- 点击"编辑"按钮,打开模态框,并填充部门信息
- 修改部门信息
- 点击"保存"按钮,发送POST请求到
/department/saveOrUpdate接口 - 服务器检查用户是否登录
- 服务器更新部门信息到数据库
- 返回更新结果
- 前端处理结果,刷新页面
4. 删除部门
- 点击"删除"按钮,弹出确认框
- 确认后,发送GET请求到
/department/delete接口 - 服务器检查用户是否登录
- 服务器从数据库删除部门
- 返回删除结果
- 前端处理结果,刷新页面
部门管理代码解析
前端代码(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. 登录验证机制(安检系统)
工作原理
- 定义注解:创建一个
@RequireLogin注解,标记在需要登录才能访问的方法上 - 配置拦截器:创建一个拦截器,拦截所有请求
- 拦截器检查:拦截器检查请求的方法是否有
@RequireLogin注解 - 登录验证:如果有注解,检查session中是否有用户信息
- 处理未登录:如果没有用户信息,返回"请先登录"的错误信息
代码解析
注解定义(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项目的搭建和配置
- 三层架构的设计和实现
- 前后端分离的开发模式
- 登录验证机制的实现
- 数据库操作的基本方法
- 网页开发的基本技能

浙公网安备 33010602011771号