手把手教你从零开始搭建SpringBoot后端项目框架
原料
新鲜的IntelliJ IDEA、一双手、以及电脑一台。
搭建框架
新建项目
打开IDE,点击File -> New Project。在左侧的列表中的选择Maven项目,点击Next。
填写GroupId和ArtifactId
什么是GroupId和ArtifactId?大家可以参考一下google出来的定义,可以参考一下。
GroupID是项目组织唯一的标识符,实际对应JAVA的包的结构,是main目录里java的目录结构。
ArtifactID就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称
简单理解一下,可以理解为GroupId就是你的Github账号,而ArtifactId就是你的具体某个项目,例如这个例子的源码,SpringBootDemo,detectiveHLH/springbootdemo
detectiveHLH就是GroupId,而ArtifactId就是后面的项目名称。
所以,这里应该填写如下(仅供参考)。
GroupId: com.detectivehlh.test ArtifactId: parent
test为项目的名称。ArtifactId代表父类,所以就写parent了。点击Next。
设置Project Name和Project Location
ProjectName就写项目的名称就好。Project Location就是项目在你本地的真实路径。填好之后,点击Next。
然后可以看到IDE已经新建好了项目。
. ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ └── java └── test.iml
然后右下角会弹出Maven projects need to be imported,选择右边的Enable Auto-Imported.然后删除src目录。
新建模块
本次项目的框架一共有四层结构,也可以说是有四个模块。分别是api、core、data、domain.我们从底层开始,自底向上开始构建模块。
domain
存放实体类
点击File -> New -> Module,在左侧的列表中选择Maven,点击Next。在ArtifactId处填 domain,一路Next。
data模块
主要是做一些对数据库的操作
点击File -> New -> Module,在左侧的列表中选择Maven,点击Next。在ArtifactId处填 data,一路Next。在模块中其实是存在相互依赖关系的。
data模块依赖domain模块的实体。所以要在data文件的配置文件中实现对domain的依赖。
打开data目录中的pom.xml文件。在
<dependencies> <dependency> <groupId>com.detectivehlh.test</groupId> <artifactId>domain</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
core模块
后端主要的业务逻辑都会在core模块中。
点击File -> New -> Module,在左侧的列表中选择Maven,点击Next。在ArtifactId处填 core,一路Next。同上,此处也需要配置依赖关系。
core模块的中的service会依赖data模块中的数据。
打开core目录下的pom.xml文件。在
<dependencies> <dependency> <groupId>com.detectivehlh.test</groupId> <artifactId>data</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
api模块
主要是存放供前端调用的接口。
点击File -> New -> Module,在左侧的列表中选择Maven,点击Next。在ArtifactId处填 api,一路Next。此处的api模块依赖core中的service服务。
打开api目录下的pom.xml文件。在
<dependencies> <dependency> <groupId>com.detectivehlh.test</groupId> <artifactId>core</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
让项目"走两步"
到此,框架算是搭建好了,下一步就是要让项目"走两步"来看看。此时的项目的目录如下。
. ├── api │ ├── api.iml │ ├── pom.xml │ └── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ └── java ├── core │ ├── pom.xml │ └── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ └── java ├── data │ ├── pom.xml │ └── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ └── java ├── domain │ ├── pom.xml │ └── src │ ├── main │ │ ├── java │ │ └── resources │ └── test │ └── java ├── pom.xml └── test.iml
定位到/api/src/main/java,在java目录下新建package,名字为你之前定义的groupid再加上模块名,举个例子。我这的名字就应该为com.detectivehlh.test.api,然后
在该包下新建名为Application的class。然后将代码替换成如下代码。
package com.detectivehlh.test.api; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
此时会报错,是因为springboot的各项依赖,都还没有引入项目的dependences。打开根目录下的pom.xml文件,添加如下依赖。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
然后打开api目录下的pom.xml文件。在dependencies标签中添加如下依赖。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
此时Application中就不会报错了。然后就可以启动项目了。打开Application这个类,在SpringBootApplication注解下有个绿色的启动键,点击即可启动项目。之后可在右上方启动。
启动之后,打开http://localhost:8080,如果页面显示
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.Tue Sep 18 19:01:11 CST 2018
There was an unexpected error (type=Not Found, status=404).
No message available
那么一个简单的springboot应用就可以启动成功了。
实现controller层
在com.detectivehlh.test.api包下,新建一个名为controller的包。然后新建名为HelloController的class。
将其全部替换为如下代码(包名根据你的项目命名自行修改)。
package com.detectivehlh.test.api.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello, SpringBoot"; } }
重新启动项目,访问http://localhost:8080/hello,就可以看到页面显示如下信息。
Hello, SpringBoot
@RestController注解比较适用于Restful风格的API,如果接口只关心数据,不做server render,就可以使用@RestController注解。
如果接口需要返回模版页面,则需要使用@Controller注解。
@GetMapping注解,是将HTTP Get请求映射到我们自定义的hello方法上。
实现service层
新建CoreConfiguration
定位到/core/src/main/java,在java目录下新建名为com.detectivehlh.test.core的包。然后在该包新建名为CoreConfiguration的Class。
将其全部替换为如下代码(包名根据你的项目命名自行修改)。
package com.detectivehlh.test.core; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * @author detectiveHLH * @date 2018/09/13 */ @ComponentScan @Configuration public class CoreConfiguration { }
引入依赖
此时会报错,同样是因为依赖没有引入。在core的pom.xml文件中的dependencies标签中添加如下依赖。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.5.RELEASE</version> </dependency>
稍等片刻,就不会有报错提示了。
新建Interface
在com.detectivehlh.test.core包下新建一个名为service的包。在service包下新建一个Class,
名字为HelloService,类型选择Interface。然后修改代码如下(包名根据你的项目命名自行修改)。
package com.detectivehlh.test.core.service; public interface HelloService { String sayHello(); }
新建实现类
在service目录下新建名为impl的包。然后在impl下新建名为HelloServiceImpl的类。修改代码如下(包名根据你的项目命名自行修改)。
package com.detectivehlh.test.core.service.impl; import com.detectivehlh.test.core.service.HelloService; import org.springframework.stereotype.Service; @Service public class HelloServiceImpl implements HelloService { @Override public String sayHello() { return "Hello, SpringBoot"; } }
调用实现类
修改HelloController中的 hello 方法的代码如下(包名根据你的项目命名自行修改)。
package com.detectivehlh.test.api.controller; import com.detectivehlh.test.core.service.HelloService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * RestController * 定义为Restful风格的API控制器 */ @RestController public class HelloController { @Autowired private HelloService helloService; @GetMapping("/hello") public String hello() { return helloService.sayHello(); } }
此时helloService会报错,这是因为我们没有将HelloService这个添加到Bean容器中来。修改Application类代码如下(包名根据你的项目命名自行修改)。
package com.detectivehlh.test.api; import com.detectivehlh.test.core.CoreConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Import; @SpringBootApplication @Import(CoreConfiguration.class) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
此时再访问http://localhost:8080/hello,就可以看到如下正常的输出了。
Hello, SpringBoot
打通数据库
实现了简单的service,下一步就是要连接数据库。假设现在在你本地已经有了mysql服务。有名为test的数据库,该数据库下有名为user_role的表。表结构如下。
数据库表名和表数据
column_name | column_value |
---|---|
id | 用户id |
name | 用户名 |
并且有了数据
column_name | column_value |
---|---|
id | name |
1 | detectiveHLH |
新建实体类
定位到/domain/src/main/java,在java目录下新建名为com.detectivehlh.test.domain的包。在该包下新建entity包。
在entity下新建名为BaseEntity的抽象类。修改代码如下。
package com.detectivehlh.test.domain.entity; public abstract class BaseEntity { private long createdAt; private String createdBy; private long updatedAt; private String updatedBy; public long getCreatedAt() { return createdAt; } public void setCreatedAt(long createdAt) { this.createdAt = createdAt; } public String getCreatedBy() { return createdBy; } public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } public long getUpdatedAt() { return updatedAt; } public void setUpdatedAt(long updatedAt) { this.updatedAt = updatedAt; } public String getUpdatedBy() { return updatedBy; } public void setUpdatedBy(String updatedBy) { this.updatedBy = updatedBy; } }
在entity下新建名为UserRole的类。代码如下。
package com.detectivehlh.test.domain.entity; public class UserRole extends BaseEntity { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
新建dao层
实现与数据库交互的mapper。
定位到/data/src/main/java,在java目录下新建名为com.detectivehlh.test.data的包。在该包下新建名为dao的包和名为
DataConfiguration的类。然后在dao包下新建名为UserRoleMapper的类。DataConfiguration代码如下。
package com.detectivehlh.test.data; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; /** * @author duzhengkang * @date 2018/6/25 */ @ComponentScan @Configuration @MapperScan("com.detectivehlh.test.data.dao") public class DataConfiguration { }
将UserRoleMapper的代码修改为如下。
package com.detectivehlh.test.data.dao; import com.detectivehlh.test.domain.entity.UserRole; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; @Mapper @Repository public interface UserRoleMapper { /** * 查询所有的用户角色 * @return */ List<UserRole> all(); }
此时代码会报错,同样的依赖原因。打开根目录下的pom.xml文件。添加如下依赖。
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.2.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency>
添加如上依赖,稍等片刻,就不会报错了。但是此时运行项目依旧会报错。是因为我们引入了mybatis但是却没有配置文件。以及没有将mapper注入到容器中去。
修改Application中的代码如下。
package com.detectivehlh.test.api; import com.detectivehlh.test.core.CoreConfiguration; import com.detectivehlh.test.data.DataConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Import; @SpringBootApplication @Import({CoreConfiguration.class, DataConfiguration.class}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
mapper就被注入到容器中去了。下一步需要添加配置文件。定位到/api/src/main/resources,新建application.yaml文件。
修改代码如下。
spring: application: name: test # 数据库配置 datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 9687Luohongwei url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true # mapper文件配置 mybatis: mapper-locations: classpath:mapper/*.xml configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
修改完毕后,启动项目,访问http://localhost:8080/hello,就可以看到正常输出了。
实现mapper
定位到/data/src/main/resources,新建名为mapper的包。在mapper包下新建名为UserRoleMapper的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="com.detectivehlh.test.data.dao.UserRoleMapper"> <!--用于与数据库字段作一一对应--> <resultMap id="userRoleMap" type="com.detectivehlh.test.domain.entity.UserRole"> <result column="id" property="id"/> <result column="name" property="name"/> </resultMap> <!--查询下方列出的所有列--> <sql id="allColumns"> id, name </sql> <!--定义表名--> <sql id="tableName"> user_role </sql> <select id="all" resultMap="userRoleMap"> SELECT <include refid="allColumns"/> FROM <include refid="tableName"/> ORDER BY id DESC </select> </mapper>
一定注意namespace是否准确。
调用mapper
修改实现类HelloServiceImpl代码如下。
package com.detectivehlh.springbootdemo.core.service.impl; import com.detectivehlh.springbootdemo.core.service.HelloService; import com.detectivehlh.springbootdemo.data.dao.UserRoleMapper; import com.detectivehlh.springbootdemo.domain.entity.UserRole; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class HelloServiceImpl implements HelloService { @Autowired private UserRoleMapper userRoleMapper; @Override public List<UserRole> createToken(String key) { List<UserRole> data = userRoleMapper.all(); return data; } }
此时会报错,是因为实现类中的返回类型已经变成了List
package com.detectivehlh.test.core.service; import com.detectivehlh.test.domain.entity.UserRole; import java.util.List; public interface HelloService { List<UserRole> sayHello(); }
让我们回到controller中,我们发现在HelloController中也有报错。这个错误同样也是因为返回类型不一致的原因,修改代码如下。
package com.detectivehlh.test.api.controller; import com.detectivehlh.test.core.service.HelloService; import com.detectivehlh.test.domain.entity.UserRole; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * RestController * 定义为Restful风格的API控制器 */ @RestController public class HelloController { @Autowired private HelloService helloService; @GetMapping("/hello") public List<UserRole> hello() { return helloService.sayHello(); } }
然后启动项目,访问http://localhost:8080/hello。就可以看到,接口返回了user_role表中的所有数据。
[ { "createdAt": 0, "createdBy": null, "updatedAt": 0, "updatedBy": null, "id": 1, "name": "Tom" } ]
此时虽然能够正常访问,但是会在控制台报如下警告。
Tue Sep 18 20:40:22 CST 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
在com.detectivehlh.test.api包下新建config包,在config包中新建DbConfig文件。代码如下。
package com.detectivehlh.test.api.config; import com.alibaba.druid.pool.DruidDataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; /** * DbConfig * * @author detectiveHLH * @date 2018-07-27 10:35 **/ @Configuration @ConfigurationProperties @EnableTransactionManagement public class DbConfig { @Bean @ConfigurationProperties("spring.datasource") public DataSource dataSource(){ DruidDataSource dataSource = new DruidDataSource(); return dataSource; } @Bean public JdbcTemplate jdbcTemplate(){ return new JdbcTemplate(dataSource()); } @Bean public PlatformTransactionManager transactionManager(){ DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource()); return dataSourceTransactionManager; } }
重启启动项目,访问接口时就不会有警告了。
最后的代码目录结构如下。
. ├── api │ ├── api.iml │ ├── pom.xml │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ └── detectivehlh │ │ │ │ └── test │ │ │ │ └── api │ │ │ │ ├── Application.java │ │ │ │ ├── config │ │ │ │ │ └── DbConfig.java │ │ │ │ └── controller │ │ │ │ └── HelloController.java │ │ │ └── resources │ │ │ └── application.yml │ │ └── test │ │ └── java │ └── target │ ├── classes │ │ ├── application.yml │ │ └── com │ │ └── detectivehlh │ │ └── test │ │ └── api │ │ ├── Application.class │ │ ├── config │ │ │ └── DbConfig.class │ │ └── controller │ │ └── HelloController.class │ └── generated-sources │ └── annotations ├── core │ ├── pom.xml │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ └── detectivehlh │ │ │ │ └── test │ │ │ │ └── core │ │ │ │ ├── CoreConfiguration.java │ │ │ │ └── service │ │ │ │ ├── HelloService.java │ │ │ │ └── impl │ │ │ │ └── HelloServiceImpl.java │ │ │ └── resources │ │ └── test │ │ └── java │ └── target │ ├── classes │ │ └── com │ │ └── detectivehlh │ │ └── test │ │ └── core │ │ ├── CoreConfiguration.class │ │ └── service │ │ ├── HelloService.class │ │ └── impl │ │ └── HelloServiceImpl.class │ └── generated-sources │ └── annotations ├── data │ ├── pom.xml │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ └── detectivehlh │ │ │ │ └── test │ │ │ │ └── data │ │ │ │ ├── DataConfiguration.java │ │ │ │ └── dao │ │ │ │ └── UserRoleMapper.java │ │ │ └── resources │ │ │ └── mapper │ │ │ └── UserRoleMapper.xml │ │ └── test │ │ └── java │ └── target │ ├── classes │ │ ├── com │ │ │ └── detectivehlh │ │ │ └── test │ │ │ └── data │ │ │ ├── DataConfiguration.class │ │ │ └── dao │ │ │ └── UserRoleMapper.class │ │ └── mapper │ │ └── UserRoleMapper.xml │ └── generated-sources │ └── annotations ├── domain │ ├── pom.xml │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ └── detectivehlh │ │ │ │ └── test │ │ │ │ └── domain │ │ │ │ └── entity │ │ │ │ ├── BaseEntity.java │ │ │ │ └── UserRole.java │ │ │ └── resources │ │ └── test │ │ └── java │ └── target │ ├── classes │ │ └── com │ │ └── detectivehlh │ │ └── test │ │ └── domain │ │ └── entity │ │ ├── BaseEntity.class │ │ └── UserRole.class │ └── generated-sources │ └── annotations ├── pom.xml └── test.iml
写在后面
写的比较详细,如果有不对的地方,大佬尽管怼。本项目的源码在 这里
个人博客在 这里
Github在 这里,欢迎star或follow。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java之生成Pdf并对Pdf内容操作
虽说网上有很多可以在线导出Pdf或者word或者转成png等格式的工具,但是我觉得还是得了解知道是怎么实现的。一来,在线免费转换工具,是有容量限制的,达到一定的容量时,是不能成功导出的;二来,业务需求,特别是OA方面的项目,报表不单单只是在线通过浏览器登录对应的站点浏览还需有时导出Pdf格式(pdf格式为通用格式,无论是浏览器还是其他工具都能打开,因此特别是做项目实施的,除了用word编写文档之外,通常还导出一下pdf,这样一来保证给老板看时,不会因为某种原因打不开文件看不到对应的实质内容。 直接开门见山: 一、导入Maven依赖 <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>...
- 下一篇
CSS变量(自定义属性)实践指南
Sass和Less这样的预处理器,让我们的CSS代码保持良好的结构和可维护性。像变量、混合(mixins)、循环控制等特性,增强了动态编写CSS的能力,从而减少重复代码,也加快了我们开发速度。 近年来,一些动态特性开始作为规范的一部分,出现在CSS语言中。CSS变量(CSS variables),或者用它的官方称谓,叫作自定义属性(custom properties),已经可用,并且有非常棒的浏览器支持,而CSS mixins也正在取得进展。 在本文,你将学会如何使用CSS变量,并把它集成到你的CSS开发流程中,让你的样式表更好维护,且减少重复。 让我们现在就开始吧! 在这里推荐一下,我的前端学习交流群:731771211,里面都是学习前端的,群里会不定期更新最新的教程和学习方法(进群送2018web前端编程学习教程,web前端的大型互联网技术教学视频),有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的web前端党欢迎加入。 点击:加入 什么是CSS变量?如果你曾使用过某种编程语言,那么你已经很熟悉变量这个概念了。变量用于存储和更新你的程序所需要的值,以便使它运行...
相关文章
文章评论
共有0条评论来说两句吧...