一、搭建好 idea 环境
1.新建一个 Maven 工程
选择 Maven 工程
选择 JDK1.8?
2.选择自己的 Maven 仓库
?3.配置字符编码
?4.注解生效激活
?5.选择 Java 编译版本为 8
6.删除父工程的 src 文件夹
7.Maven 生命周期中,跳过单元测试
?
?
二、配置父工程
1.将父工程的打包方式设为 pom
2.编写父工程的 pom.xml 文件
<?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.lanyue</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<!--将 Maven 的父工程打包方式设置为 pom-->
<!--使用 Maven 聚合工程 时,模式为 pom(父) + 子项目
这样就可以让子模块通过 dependencies 等组件标签继承父模块,拥有统一的版本号
-->
<packaging>pom</packaging>
<!--子模块-->
<modules>
<module>payment</module>
</modules>
<!--distributionManagement 负责管理构件的发布。这是一个环境变量-->
<distributionManagement>
<!--site 标签 部署当前Maven项目的网站和文档-->
<site>
<id>lanyue</id>
<url>scp://www.lanyue.com/www/website</url>
</site>
</distributionManagement>
<!--统一管理 jar 包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<!--dependencyManagement
Maven 使用 dependencyManagement 元素来提供一种管理依赖版本号的方式
通常会在一个组织或者项目的最顶层的父 pom 中看到 dependencyManagement 元素
使用 pom.xml 中的 dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号
Maven 会沿着父子层次向上走,直到找到一个拥有 dependencyManagement 元素的项目
然后它就会使用这个 dependencyManagement 元素中指定的版本号
注意:
dependencyManagement 只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖
如果子项目中声明依赖,是不会从父项目中继承下来
只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且 version 和 scope 都读取自父项目
如果子项目中写明了版本号,则使用子项目中指定的版本号
-->
<!--子模块继承之后,提供作用,锁定版本 + 子 module 不用写 groupId 和 version-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>lanyue</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.5.RELEASE</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
三、新建子模块
3.1 配置子模块的环境
1.配置好子模块的 idea 配置
?2. 编写子模块的 pom.xml 配置文件
注意:
这时,父工程的 pom 文件会自动生成以下标签
?
3.新建 application.yml 配置文件
server:
# 服务端口号
port: 8080
servlet:
# 配置根访问路径
context-path: /springcloud
# 服务名
spring:
application:
name: cloud-payment-service
# 数据源
datasource:
# 当前数据源操作类型
type: com.alibaba.druid.pool.DruidDataSource
# mysql驱动包 com.mysql.jdbc.Driver
driver-class-name: org.gjt.mm.mysql.Driver
# mysql 的数据库地址,用户名,密码
url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
druid:
# 默认 true 为 true 时 validationQuery 必须设为非空字符串
# 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
test-on-borrow: false
# 默认 false 为 true 时 validationQuery 必须设为非空字符串
# 【建议】配置为true,不影响性能,并且保证安全性。申请连接的时候检测,
# 如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
test-while-idle: true
# 默认 true 为 true 时 validationQuery 必须设为非空字符串
# 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
test-on-return: false
# 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,
# testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
validation-query: select 1
mybatis:
# mybatis 对应的 mapper 文件都在 resources 目录下的 mapper 文件夹下
mapperLocations: classpath:mapper/*.xml
# 所有 实体类 别名类所在包
type-aliases-package: com.lanyue.springcloud.entities
4.在子模块中新建 SpringBoot 启动类
package com.lanyue.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 主启动类
*/
@SpringBootApplication
public class PaymentApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentApplication.class, args);
}
}
3.2 编写子模块的业务
1.创建数据库 springcloud
2.创建支付表
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`serial` varchar(200) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
3.新建实体类
package com.lanyue.springcloud.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 支付实体类
*/
// 替换 get set 方法
@Data
// 全参构造函数
@AllArgsConstructor
// 空参构造函数
@NoArgsConstructor
// 实现序列化接口
public class Payment implements Serializable {
private Long id;
private String serial;
}
4.新建返回结果的工具类
package com.lanyue.springcloud.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 封装返回结果的实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonResult<T> {
private Integer code;
private String message;
private T data;
// data 可能为空,这时需要定义没有 data 的构造参数
public JsonResult(Integer code, String message){
this(code, message, null);
}
}
5.新建 dao 层
?
package com.lanyue.springcloud.dao;
import com.lanyue.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
// 推荐使用 Mapper 注解
@Mapper
// 不推荐使用 @Repository 注解
// @Repository
public interface PaymentDao {
// 写入操作
public Long insert(@Param("payment") Payment payment);
// 读取操作
public Payment selectPaymentById(@Param("id") Long id);
}
6.编写 dao 层的实现代码, 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" >
<!--映射的 dao 接口-->
<mapper namespace="com.lanyue.springcloud.dao.PaymentDao">
<!--
新增
因为 application.yml 配置文件中配置了 type-aliases-package: com.lanyue.springcloud.entities(所有 实体类 别名类所在包)
所以 parameterType 直接写实体类类名即可,不必写全限定类名
若 useGeneratedKeys 参数默认是false,在进行 insert 操作后是获取不到自增的id的
如果我们需要用到主键需要将参数值改为 true
keyProperty="id" 指定把获取到的主键值注入到 实体类 的 id 属性
-->
<insert id="insert" parameterType="Payment" useGeneratedKeys="true" keyProperty="payment.id">
insert into payment(serial)
values (#{payment.serial})
</insert>
<!--对应实体类的返回结果-->
<resultMap id="BaseResultMap" type="com.lanyue.springcloud.entities.Payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="serial" property="serial" jdbcType="VARCHAR"/>
</resultMap>
<!--resultMap 指定返回结果是本文件中上面定义好的 resultMap ===> BaseResultMap-->
<select id="selectPaymentById" parameterType="Long" resultMap="BaseResultMap">
select id, serial
from payment
where id = #{id}
</select>
</mapper>
7.编写 service 层接口
?
package com.lanyue.springcloud.service;
import com.lanyue.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;
public interface PaymentService {
// 写入操作
public Long insert(@Param("payment") Payment payment);
// 读取操作
public Payment selectPaymentById(@Param("id") Long id);
}
8.编写 service 层接口实现类
?
package com.lanyue.springcloud.service.impl;
import com.lanyue.springcloud.dao.PaymentDao;
import com.lanyue.springcloud.entities.Payment;
import com.lanyue.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PaymentServiceImpl implements PaymentService {
// @Autowired 是 spring 的注解
// @Autowired
// @Resource 是 Java 自带的注解
@Resource
private PaymentDao dao;
@Override
public Long insert(Payment payment) {
return dao.insert(payment);
}
@Override
public Payment selectPaymentById(Long id) {
return dao.selectPaymentById(id);
}
}
9.编写 controller 层代码
package com.lanyue.springcloud.controller;
import com.lanyue.springcloud.entities.Payment;
import com.lanyue.springcloud.service.PaymentService;
import com.lanyue.springcloud.util.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @Controller和@RestController的区别主要有以下几点:
*
* @RestController相当于@Controller和@ResponseBody合在一起的作用;
* 如果使用@RestController注解Controller层的话,则返回的是return里面的内容,无法返回到指定的页面,配置的视图解析器InternalResourceViewResolver也就自然没有作用了
* 如果要返回到指定的页面,则需要用@Controller配合视图解析器InternalResourceViewResolver
* 如果需要返回JSON、XML或自定义mediaType内容到页面,则需要在对应的方法上加上@ResponseBody注
*/
@RestController
// 配置一级访问路径
@RequestMapping("/payment")
// 日志
@Slf4j
public class PaymentController {
@Resource
private PaymentService service;
@PostMapping(value = "/insert")
public JsonResult<Long> insert(@RequestBody Payment payment){
Long result = service.insert(payment);
if (result <= 0){
log.error("插入失败");
return new JsonResult<>(301, "插入失败", null);
}else{
log.debug("插入成功");
return new JsonResult<>(200, "插入成功", result);
}
}
@GetMapping(value = "/selectPaymentById")
public JsonResult<Payment> selectPaymentById(@RequestParam("id") Long id){
Payment payment = service.selectPaymentById(id);
if (payment != null)
return new JsonResult<>(200, "查询成功", payment);
else
return new JsonResult<>(302, "查询失败", null);
}
}
四、测试功能
?
?
|