Java项目实战【超级详细】

发布时间:2025-12-09 16:02:10 浏览次数:7

软件开发流程

角色分工


开发环境搭建

创建普通Maven项目编写pom.xml导入依赖

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.yjq</groupId><artifactId>reggie_take_out</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><version>2.2.6.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><scope>compile</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency><!-- 将对象 转化为JSON格式--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.23</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.4.5</version></plugin></plugins></build></project>

配置文件application.yml

server:port: 8080spring:application:#应用的名称,可选name: reggie_take_outdatasource:druid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db_reggie?serverTimezone=Asia/Ningbo&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: 123456mybatis-plus:configuration:#在映射实体或者属性时,将数据库中表名和字段名中的下划线去掉,按照驼峰命名法映射map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:id-type: ASSIGN_ID

启动类编写

src/main/java/com/XXX/reggie/ReggieApplication.java

package com.yjq.reggie;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@Slf4j //直接可使用log日志@SpringBootApplicationpublic class ReggieApplication {public static void main(String[] args) {SpringApplication.run(ReggieApplication.class,args);log.info("项目启动成功..."); //测试项目启动}}

配置类编写 完成MVC框架静态资源映射

config/WebMvcConfig

package com.yjq.reggie;import lombok.extern.slf4j.Slf4j;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@Slf4j //直接可使用loge@SpringBootApplicationpublic class ReggieApplication {public static void main(String[] args) {SpringApplication.run(ReggieApplication.class,args);log.info("项目启动成功...");}}

再次启动查看日志是否成功,然后访问页面http://localhost:8080/backend/index.html

ps:不管用的看看放的路径是否正确,启动类要在最外层


员工管理功能


后台登录功能

需求分析

http://localhost:8080/backend/page/login/login.html打开登陆页面
按下F12,点击登录按钮,发送请求并题交参数

package com.yjq.reggie.common;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;import lombok.extern.slf4j.Slf4j;import org.apache.ibatis.reflection.MetaObject;import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Slf4j@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {/*** 插入操作,自动填充* @param metaObject*/@Overridepublic void insertFill(MetaObject metaObject) {log.info("公共字段自动填充[insert]...");log.info(metaObject.toString());metaObject.setValue("createTime", LocalDateTime.now());metaObject.setValue("updateTime", LocalDateTime.now());metaObject.setValue("createUser", new Long(1));metaObject.setValue("updateUser", new Long(1));}/*** 更新操作,自动填充* @param metaObject*/@Overridepublic void updateFill(MetaObject metaObject) {log.info("公共字段自动填充[update]...");log.info(metaObject.toString());metaObject.setValue("updateTime", LocalDateTime.now());metaObject.setValue("updateUser", new Long(1)); }}

功能完善

回显数据涉及两个表的数据,到DishService中自定义get方法(获取dish表中基本信息以及dish_flavor中对应的口味信息)

这里使用DishDto为返回对象类型,与页面数据对应

// 根据dishId查询 菜品信息和口味信息public DishDto getByDishIdWithFlavor(Long dishId); /*** 根据id查询菜品信息和对应的口味信息* @param dishId* @return*/@Overridepublic DishDto getByDishIdWithFlavor(Long dishId) {// 只是关联查询两张表,没有涉及事务,不用加 @Transactional// 从dish表中查询 菜品的基本信息Dish dish = this.getById(dishId);DishDto dishDto = new DishDto();BeanUtils.copyProperties(dish,dishDto);// 从dish_flavor表查询 当前菜品对应的口味信息LambdaQueryWrapper<DishFlavor> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(DishFlavor::getDishId,dishId);List<DishFlavor> list = dishFlavorService.list(queryWrapper);dishDto.setFlavors(list);return dishDto;} /*** 根据id查询菜品信息和对应的口味信息* @param id* @return*/@GetMapping("/{id}")public Result<DishDto> get(@PathVariable Long id){DishDto dishDto = dishService.getByDishIdWithFlavor(id);return Result.success(dishDto);}

回显后修改保存

功能测试


自我完善部分


菜品售卖状态修改功能(批量修改)

菜品删除功能(批量删除)


套餐管理功能

新增套餐功能

需求分析

数据模型

代码开发


SetmealDish 套餐餐品

package com.yjq.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;import com.baomidou.mybatisplus.annotation.TableField;import lombok.Data;import java.io.Serializable;import java.math.BigDecimal;import java.time.LocalDateTime;/*** 套餐菜品关系*/@Datapublic class SetmealDish implements Serializable {private static final long serialVersionUID = 1L;private Long id;//套餐idprivate Long setmealId;//菜品idprivate Long dishId;//菜品名称 (冗余字段)private String name;//菜品原价private BigDecimal price;//菜品的份数private Integer copies;//排序private Integer sort;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;//是否删除private Integer isDeleted;}

SetmealDto 继承 Setmeal套餐的基本属性,
另外根据前端页面需求数据添加了特有属性

package com.yjq.reggie.dto;import com.yjq.reggie.entity.Setmeal;import com.yjq.reggie.entity.SetmealDish;import lombok.Data;import java.util.List;@Datapublic class SetmealDto extends Setmeal {//新增套餐中自选菜品的集合private List<SetmealDish> setmealDishes;//设置分页查询页面的套餐分类名称private String categoryName;}

接口和控制层省略…



1-2.套餐分类和菜品分类的数据获取(CategoryController中处理过)
3.在DishController中

/*** 套餐管理/新增套餐/* 添加菜品功能中根据套餐id查询相应的菜品* @param dish* @return*/@GetMapping("/list")public Result<List<Dish>> list(Dish dish){//构造条件查询LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();//等值查询queryWrapper.eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId());//必须是起售的菜品才显示queryWrapper.eq(Dish::getStatus,1);//排序条件:根据sort升序排,根据更新时间降序排queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);List<Dish> dishList = dishService.list(queryWrapper);return Result.success(dishList);}

4-5.图片上传下载也已经处理过了

6.需要自定义保存方法
(原因:只操作setmeal表,套餐中的菜品信息无法保存)
在SetmealService中自定义保存方法,调用setmeal和seatmeal_dish表

/*** 新增套餐,同时需要保存套餐和菜品的关联关系* @param setmealDto*/@Transactionalpublic void saveWithDish(SetmealDto setmealDto) {//保存套餐的基本信息,操作setmeal,执行insert操作this.save(setmealDto);//保存套餐和菜品的关联关系,操作setmeal_dish,执行insert操作List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();setmealDishes.stream().map((item)->{//setmealDto.getId()就是setmeal表中每次创建一个新的套餐分类自动生成的id//setSetmealId是SetmealDish套餐菜品关系中的setmealId属性,对应setmeal_dish表中的setmeal_id//新增套餐下的自选菜品的每个setmeal_id都会在setmeal表中的id中找到对应,大家想不通的去数据库看这两个表item.setSetmealId(setmealDto.getId());return item;}).collect(Collectors.toList());//保存套餐和菜品的关联信息,操作setmeal_dish,执行insert操作setmealDishService.saveBatch(setmealDishes);}

功能测试

可选菜品展示

保存功能
setmeal套餐表

setmeal_dish套餐菜品关联表

套餐信息分页查询功能

需求分析

代码开发

/*** 套餐管理分页信息展示页面* @param page* @param pageSize* @return*/@GetMapping("/page")// http://localhost:8080/setmeal/page?page=1&pageSize=10&name=123public Result<Page> pageShow(int page,int pageSize,String name){Page<Setmeal> mealPage = new Page<>(page,pageSize);Page<SetmealDto> dtoPage = new Page<>(); //为了展示 套餐分类 名称 categoryNameLambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();//分页展示面,模糊查询queryWrapper.like(name != null,Setmeal::getName,name);//根据更新时间降序排列queryWrapper.orderByDesc(Setmeal::getUpdateTime);setmealService.page(mealPage,queryWrapper);/* 上面可以展示套餐基本信息,除套餐分类 展示列*///将Setmeal中的属性复制到dtoPage,但是忽略recordsBeanUtils.copyProperties(mealPage,dtoPage,"records");List<Setmeal> records = mealPage.getRecords();List<SetmealDto> dtoList = records.stream().map((setmeal)->{SetmealDto setmealDto = new SetmealDto();BeanUtils.copyProperties(setmeal,setmealDto);//套餐分类idLong categoryId = setmeal.getCategoryId();//根据套餐分类id获得套餐分类对象Category category = categoryService.getById(categoryId);if(category != null){setmealDto.setCategoryName(category.getName());}return setmealDto;}).collect(Collectors.toList());dtoPage.setRecords(dtoList);return Result.success(dtoPage);}

功能测试


删除套餐

需求分析

代码开发

功能测试

短信发送功能

短信服务


阿里云短信服务

官网注册——>控制台——>云通信



了解即可,签名申请需要三证合一比较繁琐

模板详情

AccessKey 创建子用户安全系数高

创建用户

需求分析

数据模型

代码开发


阿里云短信服务官方文档

Java SDK使用手册

导入短信发送所需maven坐标
<!--导入短信发送所需maven坐标--><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-core</artifactId><version>4.5.16</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>aliyun-java-sdk-dysmsapi</artifactId><version>2.1.0</version></dependency>


User实体类创建
package com.yjq.reggie.entity;import lombok.Data;import java.io.Serializable;/*** 用户信息*/@Datapublic class User implements Serializable {private static final long serialVersionUID = 1L;private Long id;//姓名private String name;//手机号private String phone;//性别 0 女 1 男private String sex;//身份证号private String idNumber;//头像private String avatar;//状态 0:禁用,1:正常private Integer status;}
短信发送SMSUtils工具类
package com.yjq.reggie.utils;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.IAcsClient;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;import com.aliyuncs.exceptions.ClientException;import com.aliyuncs.profile.DefaultProfile;import com.google.gson.Gson;import com.sun.xml.internal.ws.resources.SenderMessages;/*** 短信发送工具类*/public class SMSUtils {/*** 发送短信* @param signName 签名* @param templateCode 模板* @param phoneNumber 手机号* @param param 参数*/public static void sendMessage(String signName,String templateCode,String phoneNumber,String param){//构建一个阿里云客户端, 用于发起请求。//构建阿里云客户端时需要设置AccessKey ID和AccessKey Secret。DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "<accessKeyId>", "<accessSecret>");IAcsClient client = new DefaultAcsClient(profile);//构建请求,设置请求参数。SendSmsRequest request = new SendSmsRequest();request.setSysRegionId("cn-hangzhou");request.setPhoneNumbers(phoneNumber);request.setSignName(signName);request.setTemplateCode(templateCode);request.setTemplateParam("{\"code\":\""+param+"\"}");try {SendSmsResponse response = client.getAcsResponse(request);System.out.println("短信发送成功");} catch (ClientException e) {e.printStackTrace();}}}
随机生成验证码工具类ValidateCodeUtils工具类
package com.yjq.reggie.utils;import java.util.Random;/*** 随机生成验证码工具类*/public class ValidateCodeUtils {/*** 随机生成验证码* @param length 长度为4位或者6位* @return*/public static Integer generateValidateCode(int length){Integer code =null;if(length == 4){code = new Random().nextInt(9999);//生成随机数,最大为9999if(code < 1000){code = code + 1000;//保证随机数为4位数字}}else if(length == 6){code = new Random().nextInt(999999);//生成随机数,最大为999999if(code < 100000){code = code + 100000;//保证随机数为6位数字}}else{throw new RuntimeException("只能生成4位或6位数字验证码");}return code;}/*** 随机生成指定长度字符串验证码* @param length 长度* @return*/public static String generateValidateCode4String(int length){Random rdm = new Random();String hash1 = Integer.toHexString(rdm.nextInt());String capstr = hash1.substring(0, length);return capstr;}}
修改LoginCheckFilter过滤器


需要做网站?需要网络推广?欢迎咨询客户经理 13272073477