在 Java Web 开发领域,SSM 框架(Spring + Spring MVC + MyBatis)是一套备受青睐的轻量级企业级开发框架组合,它为我们提供了高效、便捷且可维护的开发方式。接下来,让我们深入探讨一下 SSM 框架中的重要知识点。
一、Spring 框架核心要点
1. IOC(控制反转)与 DI(依赖注入)
- 概念解析
- IOC 是一种设计理念,它颠覆了传统程序中对象创建和管理的方式。在以往,我们通常在代码中直接使用
new
关键字来创建对象,这使得对象之间的依赖关系紧密耦合。而 IOC 将对象的创建和管理权交给了容器(Spring 容器)。 - DI 作为 IOC 的实现方式,通过构造函数注入、setter 方法注入和字段注入等手段,将对象之间的依赖关系在运行时动态地注入到需要的地方。
- IOC 是一种设计理念,它颠覆了传统程序中对象创建和管理的方式。在以往,我们通常在代码中直接使用
- 示例说明
- 假设我们有一个
StudentService
类依赖于DataSource
类来获取数据库连接。在传统方式下,StudentService
类中可能会这样写:
- 假设我们有一个
public class StudentService {
private DataSource dataSource = new MySqlDataSource(); // 直接创建数据源对象,耦合度高
public void saveStudent(Student student) {
// 使用数据源进行数据库操作
}
}
- 而在 Spring 中,我们可以通过配置文件或注解让 Spring 容器来管理
DataSource
的创建和注入。例如,使用构造函数注入:
public class StudentService {
private final DataSource dataSource;
@Autowired
public StudentService(DataSource dataSource) {
this.dataSource = dataSource;
}
public void saveStudent(Student student) {
// 使用注入的数据源进行数据库操作
}
}
- 这样,
StudentService
类不再负责创建DataSource
对象,它与数据源的具体实现解耦,提高了代码的可维护性和可测试性。
2. AOP(面向切面编程)
- 原理与作用
- AOP 主要用于处理横切关注点,这些关注点与业务逻辑并非直接相关,但却贯穿于多个业务模块中,比如日志记录、事务管理、安全验证等。
- 它通过将这些功能从核心业务逻辑中分离出来,封装成切面,然后在合适的时机将切面织入到业务方法的执行过程中,实现了代码的模块化和复用。
- 应用场景示例
- 以日志记录为例,在一个 Web 应用中,我们希望对每个业务方法的调用都进行日志记录。如果不使用 AOP,我们可能需要在每个业务方法中都编写类似的日志记录代码:
public class OrderService {
public void createOrder(Order order) {
System.out.println("开始创建订单...");
// 订单创建逻辑
System.out.println("订单创建成功");
}
public void cancelOrder(int orderId) {
System.out.println("开始取消订单...");
// 订单取消逻辑
System.out.println("订单取消成功");
}
}
- 而使用 AOP 后,我们可以定义一个日志切面:
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service..*.*(..))")
public void beforeMethodExecution(JoinPoint joinPoint) {
System.out.println("开始执行方法:" + joinPoint.getSignature().getName());
}
@After("execution(* com.example.service..*.*(..))")
public void afterMethodExecution(JoinPoint joinPoint) {
System.out.println("方法执行结束:" + joinPoint.getSignature().getName());
}
}
- 这样,通过在切面中定义的前置通知(
@Before
)和后置通知(@After
),无需在每个业务方法中重复编写日志记录代码,就可以实现对所有业务方法的日志记录功能。
3. Spring 框架模块
- Spring Core
- 它是 Spring 框架的基础核心模块,提供了 IOC 和 DI 的基本实现,是整个 Spring 框架的基石。所有其他模块都依赖于 Spring Core 的功能,它负责对象的创建、管理和生命周期控制等基础操作。
- Spring AOP
- 专门用于实现面向切面编程的功能模块。它提供了一系列的注解和类,用于定义切面、通知(如前置通知、后置通知、环绕通知等)以及切点表达式,使得我们能够方便地将横切关注点从业务逻辑中分离出来并进行统一管理。
- Spring Context
- 构建在 Spring Core 之上,提供了一种以应用程序上下文为中心的编程模型。它负责加载和管理 Spring 配置文件中的各种 Bean,以及处理 Bean 之间的依赖关系和生命周期。同时,它还提供了事件发布和监听机制,方便应用程序在不同阶段进行相应的处理。
- Spring Data Access
- 该模块主要用于集成各种数据访问技术,如 JDBC(Java Database Connectivity)、ORM(Object Relational Mapping)框架等。它提供了统一的数据访问抽象层,简化了数据库操作的代码编写,并且支持事务管理等功能,使得开发人员能够更加专注于业务逻辑的实现,而不必过多关注底层的数据访问细节。
二、Spring MVC 框架要点
1. MVC 设计模式的实现
- 模型(Model)
- 在 Spring MVC 中,Model 主要负责处理业务逻辑和数据存储。它可以是简单的 Java 对象(POJO),也可以是与数据库交互的实体类。例如,在一个用户管理系统中,
User
类就是一个模型,它包含了用户的属性(如用户名、密码、邮箱等)以及相关的业务方法(如用户注册、登录验证等)。
- 在 Spring MVC 中,Model 主要负责处理业务逻辑和数据存储。它可以是简单的 Java 对象(POJO),也可以是与数据库交互的实体类。例如,在一个用户管理系统中,
- 视图(View)
- View 负责将 Model 中的数据以合适的方式展示给用户。常见的视图技术有 JSP(JavaServer Pages)、Thymeleaf 等模板引擎,以及 JSON、XML 等数据格式用于前后端分离的场景。例如,在一个 Web 应用中,JSP 页面可以通过 EL(Expression Language)表达式获取 Model 中的数据,并将其渲染成 HTML 页面展示给用户。
- 控制器(Controller)
- Controller 作为 Model 和 View 之间的桥梁,接收用户的请求,调用 Model 中的业务逻辑进行处理,然后选择合适的 View 来展示处理结果。它通常使用
@Controller
注解进行标识,并且在方法上使用@RequestMapping
等注解来定义请求的路径和 HTTP 方法。例如:
- Controller 作为 Model 和 View 之间的桥梁,接收用户的请求,调用 Model 中的业务逻辑进行处理,然后选择合适的 View 来展示处理结果。它通常使用
@Controller
public class UserController {
@RequestMapping(value = "/user/login", method = RequestMethod.POST)
public String login(User user, Model model) {
// 调用用户服务进行登录验证
boolean result = userService.login(user);
if (result) {
model.addAttribute("user", user);
return "success"; // 返回成功页面视图名称
} else {
model.addAttribute("error", "登录失败,请检查用户名和密码");
return "login"; // 返回登录页面视图名称
}
}
}
2. 请求处理流程和核心组件
- DispatcherServlet
- 它是 Spring MVC 的前端控制器,所有的请求都首先经过它的处理。DispatcherServlet 负责接收用户的 HTTP 请求,并根据请求的 URL 等信息将其分发给相应的控制器进行处理。它的作用类似于一个调度中心,协调着整个请求处理流程。
- Controller
- 控制器类中的方法是具体处理请求的地方。通过在方法上使用
@RequestMapping
等注解,我们可以精确地定义每个方法所处理的请求路径和 HTTP 方法。例如,@RequestMapping(value = "/user/register", method = RequestMethod.GET)
表示该方法处理GET
请求,路径为/user/register
,用于显示用户注册页面;@RequestMapping(value = "/user/register", method = RequestMethod.POST)
则表示处理用户提交注册信息的POST
请求。
- 控制器类中的方法是具体处理请求的地方。通过在方法上使用
- ModelAndView
- 它是 Controller 处理请求后返回给 DispatcherServlet 的对象,用于携带要展示给用户的视图名称和数据。例如,在上述登录示例中,当登录成功时,返回的
ModelAndView
对象中包含了视图名称 "success" 和要在视图中展示的用户对象user
;登录失败时,则包含视图名称 "login" 和错误信息 "error"。
- 它是 Controller 处理请求后返回给 DispatcherServlet 的对象,用于携带要展示给用户的视图名称和数据。例如,在上述登录示例中,当登录成功时,返回的
三、MyBatis 框架要点
1. ORM(对象关系映射)概念和作用
- 概念理解
- ORM 是一种将对象与关系数据库之间进行映射的技术。在 Java 应用中,我们通常使用面向对象的方式进行编程,而数据库则是基于关系模型存储数据的。MyBatis 通过 XML 配置文件或者注解的方式,建立起 Java 对象与数据库表之间的映射关系,使得我们可以像操作对象一样操作数据库中的数据。
- 作用体现
- 例如,对于一个
Student
类和数据库中的student
表,我们可以通过 MyBatis 将Student
类的属性与student
表的列进行对应。这样,在进行数据库操作时,我们可以直接使用Student
对象进行增删改查操作,而无需编写繁琐的 SQL 语句来处理数据库表的字段。比如,要查询一个学生的信息,我们可以编写如下代码:
- 例如,对于一个
public class StudentMapper {
public Student getStudentById(int id) {
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
return mapper.getStudentById(id);
} finally {
sqlSession.close();
}
}
}
- 在 XML 映射文件中(假设为
StudentMapper.xml
),对应的 SQL 语句如下:
<mapper namespace="com.example.mapper.StudentMapper">
<select id="getStudentById" resultType="com.example.entity.Student">
SELECT * FROM student WHERE id = #{id}
</select>
</mapper>
- 这里通过 MyBatis 的映射,我们可以直接使用
StudentMapper
接口中的方法来执行查询操作,将数据库查询结果自动映射为Student
对象,极大地简化了数据库操作代码,提高了开发效率和代码的可读性。
2. MyBatis 的工作原理和核心组件
- SqlSessionFactory
- 它是 MyBatis 的核心对象之一,负责创建
SqlSession
。SqlSessionFactory
的创建通常是通过读取配置文件(如mybatis-config.xml
)来完成的。在配置文件中,我们需要配置数据库连接信息、映射文件的位置等重要内容。例如:
- 它是 MyBatis 的核心对象之一,负责创建
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/example/mapper/StudentMapper.xml"/>
</mappers>
</configuration>
- 上述配置中定义了数据库连接环境和要加载的 Mapper 映射文件。
SqlSessionFactory
在创建时会根据这些配置信息来初始化数据库连接池等相关资源。 - SqlSession
SqlSession
是 MyBatis 执行 SQL 语句的关键对象。它提供了一系列方法,如查询(select
)、插入(insert
)、更新(update
)和删除(delete
)等操作。我们可以通过SqlSession
获取 Mapper 接口的代理对象,然后调用代理对象的方法来执行对应的 SQL 语句。例如:
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = mapper.getStudentById(1);
// 对查询到的学生对象进行操作
} finally {
sqlSession.close();
}
- 在这个示例中,首先通过
sqlSessionFactory.openSession()
获取一个SqlSession
实例,然后获取StudentMapper
接口的代理对象,调用getStudentById
方法执行查询操作,最后关闭SqlSession
以释放资源。 - Mapper 接口和 XML 映射文件
- Mapper 接口定义了操作数据库的方法签名,它是一种面向接口编程的方式,使得代码更加清晰和易于维护。而 XML 映射文件则用于将 Mapper 接口中的方法与实际的 SQL 语句进行映射。例如,在
StudentMapper
接口中有一个insertStudent
方法:
- Mapper 接口定义了操作数据库的方法签名,它是一种面向接口编程的方式,使得代码更加清晰和易于维护。而 XML 映射文件则用于将 Mapper 接口中的方法与实际的 SQL 语句进行映射。例如,在
public interface StudentMapper {
void insertStudent(Student student);
}
- 在对应的
StudentMapper.xml
文件中,有如下映射:
<mapper namespace="com.example.mapper.StudentMapper">
<insert id="insertStudent" parameterType="com.example.entity.Student">
INSERT INTO student (name, age, grade) VALUES (#{name}, #{age}, #{grade})
</insert>
</mapper>
- 这里通过
<insert>
标签将insertStudent
方法与插入学生信息的 SQL 语句进行了映射,#{name}
、#{age}
和#{grade}
是 MyBatis 的参数占位符,会在执行 SQL 语句时被实际的参数值替换。通过这种方式,MyBatis 实现了 Java 方法与 SQL 语句的无缝对接,提高了代码的可维护性和灵活性。
四、SSM 框架整合要点
1. 配置文件整合
- 在 SSM 框架整合中,配置文件的整合是关键的一步。首先,在
web.xml
文件中,我们需要配置DispatcherServlet
(Spring MVC 的前端控制器)和可能需要的 Spring 监听器(如ContextLoaderListener
)。例如:
<web-app>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
- Spring 的配置文件(通常为
application-context.xml
)中,需要配置 IOC 容器的组件、AOP 切面、与 MyBatis 的整合等内容。例如,配置数据源和SqlSessionFactory
:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="user" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
- MyBatis 也有自己的配置文件(
mybatis-config.xml
),主要用于配置全局参数、类型别名、插件等,并且需要将 Mapper 接口的映射文件包含进去。例如:
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<typeAliases>
<package name="com.example.entity"/>
</typeAliases>
<plugins>
<!-- 可以配置MyBatis插件 -->
</plugins>
<mappers>
<mapper resource="com/example/mapper/StudentMapper.xml"/>
</mappers>
</configuration>
2. 数据传递和共享
- 在 SSM 框架中,数据的传递和共享主要发生在 Spring MVC 和 MyBatis 之间。Spring MVC 的控制器接收用户请求后,将请求参数封装成对象,然后传递给 MyBatis 的 Mapper 接口进行数据库操作。例如,在一个用户注册功能中,控制器接收用户提交的注册信息,封装成
User
对象,然后调用 MyBatis 的UserMapper
接口的插入方法将用户信息保存到数据库。 - Spring 框架在这个过程中起到了重要的协调作用。通过 IOC 容器,控制器和 Mapper 接口的实例可以被正确地创建和注入。同时,Spring 还提供了
Model
或者ModelAndView
等对象,用于在控制器和视图之间传递数据。从 MyBatis 获取的数据可以通过这些对象传递给视图进行展示。例如,在控制器方法中:
@RequestMapping(value = "/user/register", method = RequestMethod.POST)
public String registerUser(User user, Model model) {
try {
userMapper.insertUser(user);
model.addAttribute("message", "注册成功");
} catch (Exception e) {
model.addAttribute("message", "注册失败:" + e.getMessage());
}
return "register_result";
}
- 这里将注册结果信息存储在
Model
对象中,然后返回视图名称 "register_result",在对应的视图页面中可以通过 EL 表达式获取message