太原理工大学软件架构实践 -- 基于JavaEE的企业级应用开发精要

发布时间:2026/6/24 2:12:07

太原理工大学软件架构实践 -- 基于JavaEE的企业级应用开发精要 1. JavaEE企业级开发的核心框架选择第一次接触企业级应用开发时面对琳琅满目的技术框架确实容易眼花缭乱。在太原理工大学的软件架构实践课程中我们主要聚焦Spring全家桶和MyBatis这套黄金组合。为什么选择它们这要从实际项目需求说起。Spring框架就像企业应用的骨架它的IOC容器解决了对象管理的难题。我参与过的一个电商项目中曾经因为手动创建对象导致代码耦合度过高后来改用Spring后模块之间的依赖关系变得清晰可见。比如订单服务需要调用支付服务传统写法可能是// 传统紧耦合写法 PaymentService payment new PaymentServiceImpl(); orderService.setPaymentService(payment);而使用Spring后只需要在类中添加注解Service public class OrderServiceImpl { Autowired private PaymentService paymentService; //... }MyBatis则是处理数据持久化的利器。相比Hibernate的全自动ORMMyBatis的半自动化特点让SQL更加可控。在需要复杂查询优化的场景下这点尤为重要。记得在开发教务管理系统时有个多表联查的绩点统计功能用MyBatis的动态SQL只用了20行就实现了原本需要50多行JDBC代码的功能。2. Spring IOC容器的实战技巧很多同学刚开始理解IOC(控制反转)概念时会觉得抽象其实可以把它想象成对象管家。在电商系统开发中商品服务、库存服务、订单服务之间有着复杂的依赖关系如果手动管理这些对象的创建和销毁代码很快就会变得难以维护。Spring提供了三种依赖注入方式实际开发中最常用的是注解方式// 构造器注入 Service public class OrderService { private final PaymentService paymentService; Autowired public OrderService(PaymentService paymentService) { this.paymentService paymentService; } } // Setter注入 Service public class UserService { private UserRepository userRepository; Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository userRepository; } } // 字段注入(最简单但不推荐) Service public class ProductService { Autowired private InventoryService inventoryService; }在课程项目中我建议使用构造器注入因为它明确声明了必需依赖方便单元测试避免循环依赖问题对象创建后状态就是完整的3. AOP在日志和事务中的典型应用AOP(面向切面编程)是Spring另一个杀手锏。在银行系统开发时我们需要为所有核心业务方法添加操作日志如果每个方法都手动写日志代码不仅重复工作量大而且容易遗漏。使用AOP后只需要定义一个切面Aspect Component public class LoggingAspect { private static final Logger logger LoggerFactory.getLogger(LoggingAspect.class); Pointcut(execution(* com.example.bank.service.*.*(..))) public void serviceLayer() {} Around(serviceLayer()) public Object logMethodExecution(ProceedingJoinPoint joinPoint) throws Throwable { String methodName joinPoint.getSignature().getName(); logger.info(Entering method: methodName); long startTime System.currentTimeMillis(); Object result joinPoint.proceed(); long elapsedTime System.currentTimeMillis() - startTime; logger.info(Method methodName executed in elapsedTime ms); return result; } }Spring事务管理也是基于AOP实现的。在订单支付场景中我们需要保证扣减库存、创建订单、记录流水三个操作要么全部成功要么全部失败Service public class OrderServiceImpl implements OrderService { Autowired private InventoryMapper inventoryMapper; Autowired private OrderMapper orderMapper; Transactional(rollbackFor Exception.class) public void createOrder(OrderDTO orderDTO) { // 扣减库存 inventoryMapper.reduceStock(orderDTO.getProductId(), orderDTO.getQuantity()); // 创建订单 Order order convertToOrder(orderDTO); orderMapper.insert(order); // 记录支付流水 paymentService.createPaymentRecord(order); } }4. MyBatis高效数据访问实践MyBatis的XML配置方式虽然灵活但对于简单CRUD操作略显繁琐。在实际项目中我推荐使用MyBatis-Plus这个增强工具它能大幅减少样板代码。比如用户管理模块的基础CRUD传统MyBatis需要定义UserMapper接口编写UserMapper.xml实现各种查询方法而使用MyBatis-Plus后// 只需定义接口继承BaseMapper public interface UserMapper extends BaseMapperUser { // 已经内置了各种CRUD方法 } // 服务层调用示例 Service public class UserServiceImpl implements UserService { Autowired private UserMapper userMapper; public PageUser queryUsers(int pageNum, int pageSize) { PageUser page new Page(pageNum, pageSize); return userMapper.selectPage(page, null); } }对于复杂查询MyBatis的动态SQL依然不可替代。在开发商品搜索功能时我们需要根据多种条件组合查询select idsearchProducts resultTypeProduct SELECT * FROM product where if testname ! null and name ! AND name LIKE CONCAT(%, #{name}, %) /if if testminPrice ! null AND price #{minPrice} /if if testmaxPrice ! null AND price #{maxPrice} /if if testcategoryIds ! null and categoryIds.size() 0 AND category_id IN foreach collectioncategoryIds itemid open( separator, close) #{id} /foreach /if /where ORDER BY choose when testsortBy price_ascprice ASC/when when testsortBy price_descprice DESC/when otherwisecreate_time DESC/otherwise /choose /select5. SpringMVC RESTful API设计现代Web应用前后端分离已成主流RESTful API设计是必备技能。在校园论坛系统开发中我们设计了这样的API结构GET /api/posts - 获取帖子列表 POST /api/posts - 创建新帖子 GET /api/posts/{id} - 获取帖子详情 PUT /api/posts/{id} - 更新帖子 DELETE /api/posts/{id} - 删除帖子对应的SpringMVC控制器RestController RequestMapping(/api/posts) public class PostController { Autowired private PostService postService; GetMapping public Result listPosts(RequestParam(required false) String keyword, RequestParam(defaultValue 1) int page, RequestParam(defaultValue 10) int size) { PagePostVO posts postService.searchPosts(keyword, page, size); return Result.success(posts); } PostMapping public Result createPost(Valid RequestBody CreatePostDTO dto) { PostVO post postService.createPost(dto); return Result.success(post); } GetMapping(/{id}) public Result getPost(PathVariable Long id) { PostDetailVO post postService.getPostDetail(id); return Result.success(post); } PutMapping(/{id}) public Result updatePost(PathVariable Long id, Valid RequestBody UpdatePostDTO dto) { postService.updatePost(id, dto); return Result.success(); } DeleteMapping(/{id}) public Result deletePost(PathVariable Long id) { postService.deletePost(id); return Result.success(); } }统一异常处理也是API开发中的重要环节ControllerAdvice public class GlobalExceptionHandler { ExceptionHandler(MethodArgumentNotValidException.class) ResponseBody public Result handleValidationException(MethodArgumentNotValidException ex) { ListString errors ex.getBindingResult() .getFieldErrors() .stream() .map(FieldError::getDefaultMessage) .collect(Collectors.toList()); return Result.fail(400, 参数校验失败, errors); } ExceptionHandler(BusinessException.class) ResponseBody public Result handleBusinessException(BusinessException ex) { return Result.fail(ex.getCode(), ex.getMessage()); } }6. 企业级应用的分层架构设计良好的分层架构是项目可维护性的保障。在开发图书馆管理系统时我们采用了典型的三层架构com.example.library ├── config - 配置类 ├── controller - 表现层 ├── service - 业务逻辑层 │ ├── impl - 服务实现 ├── dao - 数据访问层 ├── entity - 实体类 ├── dto - 数据传输对象 ├── vo - 视图对象 ├── util - 工具类 └── exception - 异常类各层职责明确Controller处理HTTP请求参数校验返回响应Service业务逻辑实现事务控制DAO数据库操作SQL执行DTO接口传输数据对象VO视图展示数据对象在微服务架构中还可以进一步拆分library-service ├── user-service - 用户服务 ├── book-service - 图书服务 ├── borrow-service - 借阅服务 └── gateway - API网关7. 项目实战从零搭建教务管理系统让我们通过一个简化版的教务管理系统串联前面讲到的各项技术。系统主要功能包括学生管理课程管理选课管理成绩管理数据库设计核心表CREATE TABLE student ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_no VARCHAR(20) UNIQUE, name VARCHAR(50), gender CHAR(1), class_id BIGINT ); CREATE TABLE course ( id BIGINT PRIMARY KEY AUTO_INCREMENT, code VARCHAR(20) UNIQUE, name VARCHAR(100), credit INT, teacher_id BIGINT ); CREATE TABLE student_course ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_id BIGINT, course_id BIGINT, score DECIMAL(5,2), UNIQUE KEY (student_id, course_id) );选课业务实现示例Service Transactional public class CourseSelectionServiceImpl implements CourseSelectionService { Autowired private StudentMapper studentMapper; Autowired private CourseMapper courseMapper; Autowired private StudentCourseMapper studentCourseMapper; public void selectCourse(Long studentId, Long courseId) { // 检查学生是否存在 Student student studentMapper.selectById(studentId); if (student null) { throw new BusinessException(学生不存在); } // 检查课程是否存在 Course course courseMapper.selectById(courseId); if (course null) { throw new BusinessException(课程不存在); } // 检查是否已选过该课程 if (studentCourseMapper.existsByStudentAndCourse(studentId, courseId)) { throw new BusinessException(不能重复选课); } // 创建选课记录 StudentCourse sc new StudentCourse(); sc.setStudentId(studentId); sc.setCourseId(courseId); sc.setScore(null); // 初始成绩为空 studentCourseMapper.insert(sc); } }8. 性能优化与常见问题排查在企业级应用开发中性能问题往往在数据量增大后才会暴露。以下是一些实战中总结的经验MyBatis性能优化使用二级缓存在mapper.xml中添加cache/标签批量操作使用foreach标签实现批量插入insert idbatchInsert INSERT INTO student_course (student_id, course_id) VALUES foreach collectionlist itemitem separator, (#{item.studentId}, #{item.courseId}) /foreach /insert延迟加载在association或collection标签中设置fetchTypelazySpring事务常见问题事务不生效检查方法是否为public是否被同类中其他方法调用事务不回滚确认异常类型是否在rollbackFor中指定长事务问题避免在事务中进行远程调用或复杂计算连接池配置建议spring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 idle-timeout: 600000 max-lifetime: 1800000 connection-timeout: 30000日志排查技巧在application.properties中添加logging.level.org.springframework.jdbcDEBUG logging.level.org.mybatisDEBUG9. 现代JavaEE技术演进虽然我们课程以传统JavaEE技术为主但了解技术发展趋势也很重要。Spring Boot已经成为了新标准它简化了配置内置Tomcat让开发更加高效。从传统Spring迁移到Spring Boot的主要变化配置方式从XML转为注解和application.yml依赖管理使用starter简化依赖部署方式从WAR部署变为可执行JARSpring Cloud为微服务提供了完整解决方案服务注册与发现Eureka/Nacos配置中心Spring Cloud Config/Nacos服务调用OpenFeign熔断降级Sentinel/Hystrix网关Spring Cloud Gateway在开发新项目时建议技术选型Web框架Spring Boot Spring MVCORMMyBatis-Plus数据库MySQL/PostgreSQL缓存Redis消息队列RabbitMQ/RocketMQ构建工具Maven/Gradle

相关新闻