SpringBoot是Spring框架对“约定大于配置(Convention over Configuration)”理念的最佳实践。SpringBoot应用本质上就是一个基于Spring框架的应用
Spring Cloud则是一系列框架的有序集合
我的理解如下图:
实际使用
使用idea
我们新建一个maven项目,选择一个网站项目。
为项目命名TemplateTestSite(图中项目名称有点不对)
选择了自己的maven和本地仓库
修改编译版本为jdk8,生效注解, 字符编码改为utf-8
new一个module,命名为cloud-provider-service8001
什么都不选直接下一步
创建如下目录不要的可以删掉
全部文件路径如下
流程如下
添加父POM 文件,如下
<?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>org.example</groupId>
<artifactId>TemplateTestSite</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cloud-provider-service8001</module>
</modules>
<!-- 统一管理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.18.10</lombok.version>
<!--<mysql.version>8.0.18</mysql.version>-->
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>2.1.1</mybatis.spring.boot.version>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本+子 modlue 不用写 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</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>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.2.RELEASE</version>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
添加子moudle的pom文件
<?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">
<parent>
<artifactId>TemplateTestSite</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-service8001</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- jdbc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
</dependencies>
</project>
基本上运行到这里,我们加个springboot的主启动类,就可以启动服务器了,
我们以前配置的tomcat呢?怎么不用启动tomcat?怎么不用导入mvc框架包?
我们点开pom里面的,start-web 这个也称为springboot的启动依赖。
他会帮我们把很多所需要的依赖全部依赖。简化了我们的操作。
之后,添加springboot配置文件application.yml,配置端口
server:
port: 8001
然后添加以下java类
1、SpringBoot的启动类
可以看出,我们使用了@SpringBootApplication注解就实现了程序的所有基础配置。这个体现了Springboot的自动装配特点
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author: SRnO
* @date: 2021/6/24
* @Description: Spring Boot启动类
*/
@SpringBootApplication
public class TestMain8001 {
public static void main(String[] args) {
SpringApplication.run(TestMain8001.class,args);
}
}
我们点击进去注解中
可以看出,和起步依赖一样,也是一个注解,springboot帮我们把原来需要配置的什么依赖注入之类,还有配置文件,全部自动装配了。
创建一个JsonData对象保存json数据
package org.example.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author: SRnO
* @date: 2021/6/24
* @Description: 用于接收jsonBody
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JSONData {
private long id;
private String testData;
}
添加XMLData 用于保存xml数据
package org.example.entities;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author: SRnO
* @date: 2021/6/24
* @Description:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@JacksonXmlRootElement(localName = "XMLData")
public class XMLData {
private long id;
private String testData;
}
之后添加controller
我们注意到,使用的注解是@RestController而不是@Controller,多了一个RESTful协议的规定
package org.example.controller;
/**
* @author: SRnO
* @date: 2021/6/24
* @Description:
* 控制器层,导入service层,调用service方法,
* controller通过接收前端传过来的参数进行业务操作,在返回一个指定的路径或者数据表。
* 其中就是RestController自动返回json类型的数据
*/
@RestController
@Slf4j
public class TemplateSiteController {
}
关于Restful协议,在前后端分离的系统中,前端和后端需要约定好相同的接口协议。通常为json方式。对于后端,一般返回类似{code:404,message:"",data:""}这种json报文。
Spring Boot 开发Restful 接口非常简单,是通过不同的注解来支持前端的请求,如下
Srping Boot 提供了与Rest 操作方式(GET、POST、PUT、DELETE)对应的注解:
1、@GetMapping,处理 Get 请求
2、@PostMapping,处理 Post 请求
3、@PutMapping,用于更新资源
4、@DeleteMapping,处理删除请求
5、@PatchMapping,用于更新部分资源
我们使用postman一个一个测试
1、测试postman中URL中的占位符
/**
* 测试占位符
* 使用PathVariable注解
*/
@PostMapping(value="/template/test/placeholder/{name}/{id}")
public CommonResult placeholder(@PathVariable("name") String name , @PathVariable("id") String id){
String result = "placeholder name = "+name+" id = "+ id;
return new CommonResult(200,"placeholder:",result);
}
2、测试postman中url中param
/**
* 测试数据库插入,数据库的data数据通过post的param导入。
* @param data
* @return
*/
@PostMapping(value="/template/test/insert")
public CommonResult insert(JSONData data)
{
int result= templateDataService.create(data);
return new CommonResult(200,"数据插入成功:",result);
}
结果后续在展示。
3、测试postman中body里面from表单提交
/**
* 测试接收form表单
* 使用RequestParam注解
*
* form-data对应的是页以form表单提交传值的情形
* 等价于http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件。当上传的字段是文件时,会有Content-Type来表名文件类型;content-disposition,用来说明字段的一些信息;
* 由于有boundary隔离,所以multipart/form-data既可以上传文件,也可以上传键值对,它采用了键值对的方式,所以可以上传多个文件
*
* POST HTTP/1.1
* Host: test.app.com
* Cache-Control: no-cache
* Postman-Token: 59227787-c438-361d-fbe1-75feeb78047e
* Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
*
* ------WebKitFormBoundary7MA4YWxkTrZu0gW
* Content-Disposition: form-data; name="filekey"; filename=""
* Content-Type:
*
*
* ------WebKitFormBoundary7MA4YWxkTrZu0gW
* Content-Disposition: form-data; name="textkey"
*
* tttttt
* ------WebKitFormBoundary7MA4YWxkTrZu0gW--
*/
@PostMapping(value="/template/test/from")
public CommonResult form(@RequestParam("name") String name , @RequestParam("file") MultipartFile file){
String result = "form name = "+name+" file size= "+ file.getSize()+" file name="+file.getOriginalFilename();
return new CommonResult(200,"form:",result);
}
4、测试postman中body里面x-www-from-urlencoded
/**
* 测试接收form表单
* 使用RequestParam注解
*
* 即application/x-www-from-urlencoded,将表单内的数据转换为Key-Value。
*
* POST HTTP/1.1
* Host: test.app.com
* Content-Type: application/x-www-form-urlencoded
* Cache-Control: no-cache
* Postman-Token: e00dbaf5-15e8-3667-6fc5-48ee3cc89758
*
* key1=value1&key2=value2
*/
@PostMapping(value="/template/test/formUrl")
public CommonResult formUrl(@RequestParam("name") String name , @RequestParam("id") String id){
String result = "form name = "+name+" id= "+ id;
return new CommonResult(200,"formUrl:",result);
}
5、测试postman中body,raw中的json ,相当于Content-Type:application/json
/**
* 测试接收body
* 使用RequestBody注解
* raw对应的是入参是任意格式的可以上传任意格式的【文本】,此处上传json
*
*/
@PostMapping(value="/template/test/raw/json")
public CommonResult rawJson(@RequestBody JSONData data){
return new CommonResult(200,"TemplateDataJSON:",data.toString());
}
6、测试postman中body,raw中的xml ,相当于Content-Type:application/xml
/**
* 测试接收body
* 使用RequestBody注解
* raw对应的是入参是任意格式的可以上传任意格式的【文本】,此处上传xml
*
*/
@PostMapping(value="/template/test/raw/xml")
public CommonResult rawXml(@RequestBody XMLData data){
return new CommonResult(200,"TemplateDataXml:",data.toString());
}
7、测试postman中binary, 相当于Content-Type:application/octet-stream,
/**
* 测试接收binary
* 相当于Content-Type:application/octet-stream,只可以上传二进制数据,
* 通常用来上传文件,但是一次只能上传一个文件
*/
@ResponseBody
@PostMapping(value="/template/test/binary")
public CommonResult binary( HttpServletRequest request){
try {
String str=stream2String(request.getInputStream());
return new CommonResult(200,"TemplateData:",str);
} catch (Exception e) {
e.printStackTrace();
return new CommonResult(404,"binary:",e.getMessage());
}
}
public String stream2String(InputStream inputStream) throws Exception {
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
String str = result.toString(StandardCharsets.UTF_8.name());
return str;
}
这上面postman返回的标准格式由返回数据的标准对象CommonResult产生。
package org.example.entities;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
private Integer code;
private String message;
private T data;
public CommonResult(Integer code, String message) {
this(code,message,null);
}
}
此处原理是springboot依赖jackson库,对http返回的数据进行了json转化
使用mybatis连接数据库部分:
yml中添加
server:
port: 8001
spring:
application:
name: cloud-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver # mysql 驱动包
url: jdbc:mysql://localhost:3306/templatesite?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: org.example.entity # 所有 entity 别名类所在包
添加数据库的配置文件TestMapper.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.dao.TemplateDataDao">
<resultMap id="BaseResultMap" type="org.example.entities.TemplateData">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="testData" property="testData" jdbcType="VARCHAR"/>
</resultMap>
<insert id="create" parameterType="org.example.entities.TemplateData" useGeneratedKeys="true" keyProperty="id">
insert into test(testData) values(#{testData})
</insert>
<select id="getDataById" parameterType="Long" resultMap="BaseResultMap">
select * from test where id=#{id}
</select>
</mapper>
添加dao和server
package org.example.dao;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.example.entities.JSONData;
/**
* @author: SRnO
* @date: 2021/6/24
* @Description:
* 即mapper层,对数据库进行持久化操作,他的方法是针对数据库操作的,基本用到的就是增删改查。
* 它只是个接口,只有方法名字,具体实现在mapper.xml中
*/
@Mapper
public interface TemplateDataDao {
int create(JSONData jsonData);
JSONData getDataById(@Param("id")Long id);
}
package org.example.service.impl;
import org.example.dao.TemplateDataDao;
import org.example.entities.JSONData;
import org.example.service.TemplateDataService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author: SRnO
* @date: 2021/6/24
* @Description:
*/
@Service
public class TemplateDataServiceImpl implements TemplateDataService {
@Resource
private TemplateDataDao templateDataDao;
@Override
public int create(JSONData templateData) {
return templateDataDao.create(templateData);
}
@Override
public JSONData getDataById(Long id) {
return templateDataDao.getDataById(id);
}
}
然后再controller中
@Resource
private TemplateDataService templateDataService;
/**
* 测试数据库插入,数据库的data数据通过post的param导入。
* @param data
* @return
*/
@PostMapping(value="/template/test/insert")
public CommonResult insert(JSONData data)
{
int result= templateDataService.create(data);
return new CommonResult(200,"数据插入成功:",result);
}
就这样我们基本完成了服务器的搭建。也可以再window部署并且用tomcat局域网访问。
之后我们再将其部属在我们阿里云中
我们点击右侧的maven,进行package
可以按照我们要求生成war或者jar。我们这里生成了jar包
然后putty连接我的服务器,通常我都会新建一个目录。将jar包丢入此处。然后执行命令
java -jar %地址% jar名称
但是这样子只是一次性的,关掉即关闭该线程,所以我们使用nohup指令,并且撰写脚本
start.sh
#!/bin/sh
rm -f tpid
nohup java -jar /usr/local/Program/jar/cloud-printer-provider8001-1.0-SNAPSHOT.jar --spring.config.location=application.yml > /dev/null 2>&1 &
echo $! > tpid
echo Start Success!
stop.sh
#!/bin/sh
APP_NAME=cloud-printer-provider8001-1.0-SNAPSHOT
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
echo 'Stop Process...'
kill -15 $tpid
fi
sleep 5
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
echo 'Kill Process!'
kill -9 $tpid
else
echo 'Stop Success!'
fi
check.sh
#!/bin/sh
APP_NAME=cloud-printer-provider8001-1.0-SNAPSHOT
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
if [ ${tpid} ]; then
echo 'App is running.'
else
echo 'App is NOT running.'
fi
另外如果这个脚本在window下编写的。会执行失败
打开vim。执行:set ff 出现doc,需要改成set ff=doc
执行脚本即可完成。
SpringCloudAlibaba的搭建我们下期再详细描述