Java学习记录(10) - SpringMVC(实现api接口请求)

前言

  • 通过学习Spring 以及 Servlet 相关知识, 我们已经可以进行开发 api 接口了。通过Spring实现IoC 以及 AOP 可以帮助我们更好的管理Bean以及创建实例、连接数据库等操作。
  • 通过HikariCP 可以更方便的管理数据库连接池, 避免了手动创建连接池的繁琐过程。
  • 通过MyBatis 可以更轻易的实现数据库的增删改查操作, 我们只需要定义好Mapper 接口, 并在xml 文件中实现对应的sql 语句即可。
  • 通过lombok 可以减少我们的代码量, 避免了手动编写getter 、 setter 等方法, 通过注解的形式可以自动生成相应的方法。
  • 通过 jackson-databind 可以更方便的实现json 与 java 对象的转换, 我们只需要在Controller 中添加@RequestBody 注解即可将json 字符串转换为java 对象。

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
├── pom.xml
└── src
├── main
│   ├── java
│   │   └── org
│   │   └── example
│   │   ├── AppConfig.java
│   │   ├── entity
│   │   │   └── User.java
│   │   ├── mapper
│   │   │   └── UserMapper.java
│   │   ├── service
│   │   │   └── UserService.java
│   │   ├── util
│   │   │   └── Result.java
│   │   └── controller
│   │   ├── TestController.java
│   │   └── UserController.java
│   ├── resources
│   │   ├── jdbc.properties
│   │   └── logback.xml
│   └── webapp
│   ├── WEB-INF
│   │   ├── templates
│   │   └── web.xml
│   └── static
├── mian
│   └── webapp
│   └── WEB-INF
└── test
└── java

项目依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.0</version>
</dependency>
<!-- aop 相关依赖 -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
<!-- 日志系统 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.4.4</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.4</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version> <!-- MySQL 驱动 -->
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version> <!-- 建议使用最新稳定版本 -->
<scope>provided</scope>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>3.0.0</version>
</dependency>
<!-- jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>6.0.0</version>
</dependency>
</dependencies>

项目配置

web-xml 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<web-app>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.example.AppConfig</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>
</web-app>

该配置文件的作用是将Spring的AnnotationConfigWebApplicationContext与DispatcherServlet关联起来,
并指定AppConfig类作为配置类。也就是在Servlet初始化时实现Spring的ApplicationContext的初始化。

jdbc.properties 配置文件

1
2
3
4
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

数据库的连接配置

logback.xml 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>

<logger name="org.example" level="info" additivity="false">
<appender-ref ref="STDOUT" />
</logger>

<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>

日志配置

IDEA配置

如果项目不是基于JavaEE项目创建的,则需要手动配置项目结构。在IDEA中,点击File -> Project Structure,选择Facet与Artifact(工件)。

Facet

Artifact

配置好了以后,才可以配置Tomcat服务器进行启动。

AppConfig Spring 配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package org.example;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.sql.DataSource;

@ComponentScan
@Configuration
@PropertySource("classpath:/jdbc.properties")
@EnableAspectJAutoProxy
@EnableWebMvc
@EnableTransactionManagement
@MapperScan("org.example.mapper")
public class AppConfig {
private static final Logger log = LoggerFactory.getLogger(AppConfig.class);

@Value("${jdbc.url}")
private String url;

@Value("${jdbc.username}")
private String username;

@Value("${jdbc.password}")
private String password;

@Bean
public DataSource getDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(url);
config.setUsername(username);
config.setPassword(password);
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
config.setMaximumPoolSize(5);
return new HikariDataSource(config);
}

@Bean
public PlatformTransactionManager getTransactionManager(@Autowired DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

@Bean
public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
}

该类主要作用是配置注解,开启Spring的AOP功能,开启事务管理功能,开启MyBatis的Mapper扫描功能, 以及开启WebMvc的配置。
以及创建数据库连接池HikariDataSource, 创建事务管理器DataSourceTransactionManager, 以及创建MyBatis的SqlSessionFactoryBean。

数据返回工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package org.example.util;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private Integer code;
private String message;
private T data;

// 成功响应方法
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}

public static <T> Result<T> success() {
return success(null);
}

// 失败响应方法
public static <T> Result<T> fail(Integer code, String message) {
return new Result<>(code, message, null);
}
}

该类的作用是封装数据返回结果,包括状态码、消息和数据。

实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
package org.example.entity;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class User {
private Long id;
private String username;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
private String email;
}

该类的作用是定义用户实体类,包括用户ID、用户名、密码和邮箱。使用了Lombok的@Data注解,自动生成了getter、setter、toString、equals和hashCode方法。
以及@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)注解,用于在序列化时忽略password字段。表明该字段在序列化时只可写入不可读取。

Mapper接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package org.example.mapper;

import org.apache.ibatis.annotations.*;
import org.example.entity.User;

import java.util.List;

public interface UserMapper {
@Select("SELECT * from users WHERE id = #{id}")
User getUserById(@Param("id") long id);

@Select("SELECT * from users WHERE username = #{username} and password = #{password}")
User getUserByUsernameAndPassword(@Param("username") String username, @Param("password") String password);

@Update("UPDATE users SET username = #{user.username} WHERE id = #{user.id}")
int updateUser(@Param("user") User user);

@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@Insert("INSERT INTO users (email, username, password) VALUES(#{user.email}, #{user.username}, #{user.password})")
int insertUser(@Param("user") User user);

@Select("SELECT * from users")
List<User> getUsers();
}

该接口的作用是定义用户的数据库操作方法,包括根据ID查询用户、根据用户名和密码查询用户、更新用户、插入用户和查询所有用户。
使用了MyBatis的注解,包括@Select、@Update、@Insert和@Options。

服务层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package org.example.service;

import org.example.entity.User;
import org.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional
public class UserService {
@Autowired
private UserMapper userMapper;

public User signIn(String username, String password) {
User user = userMapper.getUserByUsernameAndPassword(username, password);
if (user == null) {
throw new RuntimeException("账号不存在");
}
return user;
}

public User register(User user) {
User user1 = userMapper.getUserByUsernameAndPassword(user.getUsername(), user.getPassword());
if (user1 != null) {
throw new RuntimeException("账号已存在");
}
int result = userMapper.insertUser(user);
if (result < 0) {
throw new RuntimeException("注册失败");
}
return user;
}

public User updateUsername(User user) {
int result = userMapper.updateUser(user);
if (result < 0) {
throw new RuntimeException("修改用户名失败");
}
return user;
}

public List<User> listUser() {
return userMapper.getUsers();
}
}

该类的作用是定义用户的服务层方法,包括登录、注册、修改用户名和查询所有用户。
使用了Spring的@Service注解,表明该类是一个服务层组件。
以及@Transactional注解,开启了事务管理。

控制层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package org.example.controller;

import org.example.entity.User;
import org.example.service.UserService;
import org.example.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api")
public class UserController {
@Autowired
private UserService userService;

@GetMapping("/users")
public Result<List<User>> getUsers() {
List<User> users = userService.listUser();
return Result.success(users);
}

@PostMapping("/signin")
public Result<User> signin(@RequestBody RequestSignIn request) {
try {
User user = userService.signIn(request.username, request.password);
return Result.success(user);
} catch (RuntimeException e) {
return Result.fail(500, "登录失败");
}
}

@PostMapping("/register")
public Result<User> register(@RequestBody RequestSignUp request) {
try {
User user1 = new User();
user1.setUsername(request.username);
user1.setPassword(request.password);
user1.setEmail(request.email);
User user = userService.register(user1);
return Result.success(user);
} catch (RuntimeException e) {
return Result.fail(500, "注册失败");
}
}

public static class RequestSignIn {
public String username;
public String password;
}

public static class RequestSignUp {
public String username;
public String password;
public String email;
}
}

该类的作用是定义用户的控制层方法,包括查询所有用户、登录和注册。
使用了Spring的@RestController注解,表明该类是一个RESTful控制器。
以及@RequestMapping注解,指定了该控制器的基础路径为/api。

总结

至此,我们即可使用SpringMVC框架来构建一个简单的用户管理系统, 当启动服务之后,我们可以通过POST请求/api/register来注册一个新用户,通过POST请求/api/signin来登录该用户,通过GET请求/api/users来查询所有用户。
还有需要注意的一个点是, 在Spring项目中连接数据库时, url可以是jdbc:mysql://localhost:3306/spring_example这种不带任何参数的地址,Spring在编译时会自动的添加上数据库连接所需要的一些额外参数,但是在Servlet中, 必须使用完整的url路径,比如jdbc:mysql://localhost:3306/spring_example?useSSL=false&characterEncoding=utf8&allowPublicKeyRetrieval=true, 需要设定useSSl等参数,因为Servlet不会帮你添加上这些,会导致数据库无法正确连接。


Java学习记录(10) - SpringMVC(实现api接口请求)
https://stanlee12.github.io/2025/12/18/java-study-10/
作者
stan
发布于
2025年12月18日
许可协议