在 Java - servlet 3.0 这篇文章中我们大概了解了一下
Servlet 3.0
,在日常web
开发中我们一般都是使用SpringMVC
框架,所以这里以Servlet 3.0
注解的方式来搭建一下 SSM 框架
1、准备工作
1.1、创建 Maven 项目
填写项目的 GAV
等信息:
项目的基本结构就是下面这样:
1.2、配置依赖
首先我们在 pom.xml
中配置 Spring
、SpringMVC
、Mybatis
相关的依赖,借助于 Maven
的依赖传递机制,我们只需要引入核心的依赖即可:
<?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>
<groupId>com.example</groupId>
<artifactId>ssm-example</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.version>5.3.22</spring.version>
</properties>
<dependencies>
<!--Spring begin-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!--Spring end-->
<!--Mybatis begin-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!--junit5-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>4.0.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
业务都是不断完善的,架构也是慢慢演化的,所以这里的依赖不是固定的,有需要可以再添加
1.3、准备一个 mysql
数据库 example
,并新建一张 user
表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`gender` tinyint(4) NULL DEFAULT NULL,
`nickname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
2、整合 SpringMVC
2.1、整合分析
从 SpringMVC 官方文档 中我们知道,不仅可以通过 web.xml
的方式来配置 DispatcherServlet
,还可以通过 Java configuration
的方式来配置 DispatcherServlet
。
- 使用
ServletContext API
的形式配置
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
- 拓展
AbstractAnnotationConfigDispatcherServletInitializer
的形式配置
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { App1Config.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/app1/*" };
}
}
这里我们使用第二种方式:实现 AbstractAnnotationConfigDispatcherServletInitializer
来整合 SpringMVC
,这种方式也是官方推荐的方式:
2.2、整合
- 定义
Root WebApplicationContext
:
@Configuration
public class SpringConfig {
}
- 定义
Servlet WebApplicationContext
:
@Configuration
// SpringMVC 只需要扫描控制层即可
@ComponentScan(value = "com.example.controller")
// 开启 SpringMVC 高级配置
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
/**
* 配置静态资源访问
*
* @param configurer
*/
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
- 配置
DispatcherServlet
:
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected Filter[] getServletFilters() {
// 配置编码过滤器
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
// 配置处理请求方式的过滤器
HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
return new Filter[]{
characterEncodingFilter,
hiddenHttpMethodFilter
};
}
}
3、整合 Spring
从 SpringMVC 官方文档 中我们知道,Servlet
容器只需要扫描控制层即可,但是 Root
容器需要扫描 Service
层和 Repositiries
持久化层
@Configuration
@ComponentScan(value = "com.example", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = RestController.class),
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
})
public class SpringConfig {
...
}
3.1、配置数据源 druid
3.1.1、新建一个 jdbc.properties
来配置数据库连接信息
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://192.168.80.232:3306/example?serverTimezone=UTC
jdbc.username=root
jdbc.password=123456
3.1.2、新建一个常量类 JdbcConsts
来读取配置信息
@Data
@Component
public class JdbcConsts {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
}
当然了,只是这样并不能读取到 jdbc.properties
中的数据,我们还需要使用 @PropertySource
注解来把数据读取到内存中
@Configuration
@ComponentScan(value = "com.example", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = RestController.class),
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
})
// 加载文件到内存
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
...
}
3.1.3、配置数据源
@Configuration
@ComponentScan(value = "com.example", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = RestController.class),
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
})
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
@Bean
public DataSource dataSource(JdbcConsts jdbcConsts) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(jdbcConsts.getDriver());
dataSource.setUrl(jdbcConsts.getUrl());
dataSource.setUsername(jdbcConsts.getUsername());
dataSource.setPassword(jdbcConsts.getPassword());
return dataSource;
}
}
4、整合 Mybatis
4.1、准备工作
首先创建数据表 user
对应的 Mybatis
需要的文件:User
实体、UserMapper
接口、UserMapper.xml
4.2、配置 SqlSessionFactory
@Configuration
@ComponentScan(value = "com.example", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = RestController.class),
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
})
@PropertySource("classpath:jdbc.properties")
public class SpringConfig {
@Bean
public DataSource dataSource(JdbcConsts jdbcConsts) {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(jdbcConsts.getDriver());
dataSource.setUrl(jdbcConsts.getUrl());
dataSource.setUsername(jdbcConsts.getUsername());
dataSource.setPassword(jdbcConsts.getPassword());
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
System.out.println(dataSource);
sqlSessionFactoryBean.setDataSource(dataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setTypeAliasesPackage("com.example.domain");
//sqlSessionFactoryBean.setConfigLocation();
//sqlSessionFactoryBean.setPlugins();
Properties properties = new Properties();
properties.setProperty("mapUnderscoreToCamelCase", "true");
sqlSessionFactoryBean.setConfigurationProperties(properties);
try {
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/*.xml"));
return sqlSessionFactoryBean.getObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
4.3、配置 mapper
扫描
@Configuration
@ComponentScan(value = "com.example", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = RestController.class),
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
})
@PropertySource("classpath:jdbc.properties")
// 扫描 Mybatis Mapper 层
@MapperScan(basePackages = "com.example.mapper")
public class SpringConfig {
...
}
5、配置事务管理
...
@EnableTransactionManagement
public class SpringConfig {
...
@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
6、测试功能
6.1、测试添加数据接口
@RestController
@RequestMapping("user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("add")
public Integer add(@RequestBody User user) {
return userService.add(user);
}
}
注意:这里需要使用到
SpringMVC
的数据绑定功能,所以需要添加jackson-databind
依赖。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>x.x.x</version>
</dependency>
6.2、测试分页查询功能
可以配置分页插件 PageHelper
,参考:Mybatis - PageHelper 分页插件
这一部分代码比较多,就不粘贴在这里了,有需要的朋友可以从 Git 地址 中拉取代码