经验仅个人观点
Spring Boot 项目的代码开发流程遵循MVC(Model-View-Controller)架构,通过良好的代码组织和合理的分层设计,实现业务逻辑和数据访问的分离。通过遵循这些步骤,可以提高代码的可维护性和可扩展性,加快项目开发速度,降低开发成本。
首先,一个基础开发流程是这样的:
下面将分为六个小节来详细讲解这六个层面的内容,以及个人书写模式。(数据库除外)
一、实体类
介绍
在Spring Boot中,实体类通常包含用于映射数据库中表的字段的属性。这些属性通常与表中的列具有相同的名称和数据类型,并且通常与业务逻辑相关。
这样的实体类通常用于与数据库交互,例如通过 Spring Data JPA 或者 MyBatis 等持久化框架来将用户信息存储到数据库中,或者从数据库中检索用户信息。这种设计让你能够在应用程序中轻松地操作和管理用户信息。
内容
实体类就是一个拥有Set和Get方法的类
例如:这里是一个简单的用户的实体类:
@Data
public class User {
private Long id; // 用户ID
private String username; // 用户名,用于普通登录
private String password; // 密码,用于普通登录
private String phone; // 手机号码
}
首先上面使用了 lombok
库中的 @Data
注解,该注解会自动生成 getter
和 setter
方法、toString
方法、equals
方法以及 hashCode
方法,简化了实体类的开发。
然后 这里定义名为id
的私有(private
)属性,类型是 长整数(Long
)以及其他
编写
我在编写过程中实体类,一般类名和数据库表名一致
字段名采取小驼峰命名法,类型一般转换为Java数据类型
并且会使用@Date
来简化开发。
二、控制器
介绍
控制器是MVC(Model-View-Controller)架构中的一部分,负责处理用户请求、调用服务层方法、返回响应等工作。控制器通常包含各种接口方法,用于定义不同的请求处理逻辑。
它负责接收用户的请求并根据请求的内容来调用相应的服务(Service
)方法,最终返回响应给用户。
内容
控制器(Controller)是应用程序中处理用户请求的一部分,控制器中应至少包含以下几个必须内容:
- 路由设置
控制器需要定义路由,即指定哪些 URL 路径由控制器来处理。在现代的框架中,这通常通过注解来实现,比如 Spring MVC 中的@RequestMapping
、@GetMapping
、@PostMapping
等注解。 - 参数解析:控制器需要解析请求中携带的参数,包括路径参数、查询参数、请求体中的参数。这些参数可以作为方法的参数传入,用于处理请求(
@RequestBody
、@RequestParam
等)。 - 调用服务层:控制器一般不负责实际的业务逻辑处理,而是调用服务层(Service Layer)来执行具体的业务逻辑。因此,控制器需要与服务层进行交互。
- 返回响应:在处理完请求后,控制器需要返回适当的响应给客户端。响应可以是数据(比如 JSON 格式的数据)、视图(HTML 页面)或者其他类型的数据。
- 异常处理:控制器需要处理请求过程中可能发生的异常。良好的异常处理可以提高系统的稳定性和用户体验。通常,控制器会捕获异常并返回适当的错误信息给客户端。
- 日志记录:为了方便系统运维和问题排查,控制器通常会记录请求日志,包括请求的路径、参数、处理结果等信息,以便后续分析。
例如:这里是一个简单的登录的控制器:
@RestController
@RequestMapping("/")
public class LoginController {
@Autowired
LoginService loginService;
@PostMapping(path = "/login")
public ApiResponse login(@RequestBody User user) {
try {
Map<String, Object> result = loginService.login(user);
return ApiResponse.ok(result);
} catch (Exception e) {
return ApiResponse.of(e);
}
}
}
首先最开始是@RestController
,它结合了 @Controller
和 @ResponseBody
注解的功能,@Controller
用于定义控制器类,而 @ResponseBody
用于指示方法返回的内容直接作为 HTTP 响应体返回
然后是@RequestMapping("/")
,作用用于将请求映射到控制器方法,简单来说就是拼接接口的内容,("/")
代表无拼接参数。
之后就是定义类的代码,再下面是自动注入了LoginService
的类。
@PostMapping(path = "/login")
用于处理 POST 请求的注解,后面也是拼接接口的内容。
@RequestBody
是Spring框架的注解,用于将请求体中的JSON数据映射到User
对象中。在这里,user
参数将包含从请求中传入的用户信息(就是前端传过来的JSON数据)。
try catch
是Java中的异常处理结构,如果代码执行异常,控制将转移到catch
块。
ApiResponse
是一个自定义的类,通常用于封装接口的响应数据,以便统一格式化返回给客户端。这种方式可以使接口返回结果更加一致,并且易于客户端处理不同类型的响应。
其中包括状态码 (status code),消息 (message),数据 (data)
编写
编写过程和上面无异,个人的编写习惯。
三、服务层
介绍
Service 服务层是应用程序的一个关键组成部分,用于处理业务逻辑,实现业务规则并协调不同的数据访问对象。Service 层的设计有助于将业务逻辑与数据访问层分离,提高代码的可维护性、可测试性和可扩展性。
内容
public interface LoginService {
Map<String, Object> login(User user);
}
以上是一个简单的 LoginService
接口,它定义了一个 login
方法,接受一个 User
参数并返回一个 Map<String, Object>
类型的结果。以下是对这个接口定义的解释
编写
个人感觉:Service就像是控制类和实现层之间的中间件,负责他俩的连接
一般我在Service中除了方法的传递以外 不会编写其他代码
详细代码实现会在实现类Impl(Implementation)中实现
四、服务层实现类
介绍
在实际开发中,接口的实现类通常是整个应用程序中的关键部分,负责实现具体的业务逻辑。通过将业务逻辑从控制器层和数据访问层中分离出来,可以提高代码的模块化性和可维护性。实现类的设计应该遵循面向接口编程的原则,以确保代码的灵活性和可扩展性。
内容
@Service
public class LoginServiceImpl implements LoginService {
@Resource
private UserDao userDao;
@Autowired
private TokenService tokenService;
@Override
public Map<String, Object> login(User user) {
Map<String, Object> response = new HashMap<>();
User userInfo = userDao.getUserByUsername(user.getUsername());
if(userInfo == null) {
throw new SimpleException(ResultEnum.ACCOUNT_OR_USERNAME_NON_EXISTENT);
}
String passwordMd5 = calculateMD5(user.getPassword());
if(passwordMd5.equals(userInfo.getPassword())) {
String token = tokenService.createToken(userInfo.getId(), userInfo.getUsername()); // 创建 token
response.put("user", userInfo);
response.put("token", "Bearer "+ token);
System.out.println(token);
return response;
} else {
throw new SimpleException(ResultEnum.FAIL);
}
}
首先,类 LoginServiceImpl
,它实现了 LoginService
接口,意味着 LoginServiceImpl
类需要提供 LoginService
接口中定义的所有方法的具体实现。
首先从上往下依次有四个注解,这些注解通常用于 Spring Framework 中,用于标识和配置组件、依赖注入以及方法重写等
- @Service:
@Service
是 Spring 框架中用来标识业务逻辑层(Service 层)组件的注解。Spring 会扫描带有@Service
注解的类,并将其实例化为 Bean,以便在应用程序中进行依赖注入和使用。
- @Resource:
@Resource
是 Java EE 提供的标准注解,用于依赖注入在 Spring 中,@Resource
注解可以用于装配 Bean
- @Autowired:
@Autowired
是 Spring 框架提供的注解,用于自动装配 Bean。
- @Override:
@Override
是 Java 语言的注解,用于标识方法重写。当一个方法使用@Override
注解时,表示该方法是重写父类或接口中的方法。(LoginServiceImpl
类实现了LoginService
接口中的方法)
其他代码则是基础的实现逻辑代码,不做具体讲解。
编写
五、数据访问层
介绍
数据访问层是应用程序架构中的一个重要组成部分,负责处理数据的访问和存储。它位于业务逻辑层和数据库之间,主要用于实现与数据存储相关的操作,如数据库查询、更新、插入和删除等。
我一般使用MyBatis,在MyBatis中,Mapper和XML之间有着密切的关系。在MyBatis中,Mapper通常指的是一个Java接口,而该接口定义了数据库操作的方法。这些方法具体实现数据库并执行相应的SQL语句是在XML文件中。
内容
@Mapper
public interface UserDao {
void insertUser(User user);
}
以上代码中,@Mapper
是一个注解,表示这是一个MyBatis的Mapper接口,用来定义数据库操作的方法。
UserDao
则是一个接口,用来描述对用户(User)对象的数据库操作。详细的数据库操作实现在XML文件中
编写
一般在Mapper中只书写@Mapper
注解,和我们需要用到的操作数据方法以及参数和返回类型。
六、XML文件
介绍
在MyBatis中,XML文件扮演着非常重要的角色,用于配置SQL语句、参数映射、结果映射等信息。
接收Mapper的方法,在XML文件中做详细实现。
内容
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.hymm.dao.UserDao">
<!-- 插入用户 -->
<insert id="insertUser" parameterType="org.example.hymm.bean.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO `user` (username, password, phone, email, wechat_openid, wechat_unionid,
wechat_nickname, wechat_avatar_url, gender, language, city,
province, country, created_at, updated_at)
VALUES (#{username}, #{password}, #{phone}, #{email}, #{wechatOpenid}, #{wechatUnionid},
#{wechatNickname}, #{wechatAvatarUrl}, #{gender}, #{language}, #{city},
#{province}, #{country}, NOW(), NOW())
</insert>
</mapper>
- XML声明:
<?xml version="1.0" encoding="UTF-8" ?>
:XML声明,指定了XML版本和编码方式。<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
:指定了XML文件的DTD(文档类型定义),确保XML文件符合MyBatis的规范。
- mapper标签:
<mapper namespace="org.example.hymm.dao.UserDao">
:指定了该Mapper XML文件对应的Mapper接口的全限定名为org.example.hymm.dao.UserDao
。
- insert标签:
<insert id="insertUser" parameterType="org.example.hymm.bean.User" useGeneratedKeys="true" keyProperty="id">
:定义了一个插入操作,将User
对象插入到user
表中。parameterType="org.example.hymm.bean.User"
:指定了插入操作的参数类型为org.example.hymm.bean.User
。useGeneratedKeys="true" keyProperty="id"
:表示要使用数据库自动生成的主键,并将生成的主键值设置回User
对象的id
属性。
- 插入SQL语句:
- SQL语句中使用了
#{}
语法进行参数映射,将User
对象的属性值插入到对应的列中。 NOW()
函数用于获取当前时间,用于设置created_at
和updated_at
字段的值。
- SQL语句中使用了
以上Mapper XML文件定义了一个插入用户的操作,并配置了结果映射,确保数据库查询结果能正确映射到User
实体类的各个属性中。
编写
就是基础的使用SQL语法来操作数据库,<select>
:用于查询操作,<insert>
:用于插入操作,<update>
:用于更新操作,<delete>
:用于删除操作,以及通过其他的各种标签来实现。
至此,一个简单的SpringBoot的项目代码流程,基本完成
END