SpringBoot——基础开发(下)

1 Swagger2 自动化测试与文档

1.1 Swagger2 功能

  Swagger2 可以识别控制器中的方法,然后自动生成可视化的测试界面。
  后端开发人员编写完 Spring Boot 后端接口后,直接可视化测试就行了。无需借助 Postman 等工具,也无需编写测试类和测试方法,更无需联系前端开发确认接口是否正常。
  如果给控制器方法添加注解,还能自动生成在线 API 文档。

1.2 Spring Boot 中使用 Swagger2 流程

1)引入 Swagger2 相关依赖
  修改 pom.xml 文件,引入 Swagger2 相关依赖。

<!-- 添加swagger2相关功能 -->
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger2</artifactId>
	<version>2.9.2</version>
</dependency>
<!-- 添加swagger-ui相关功能 -->
<dependency>
	<groupId>io.springfox</groupId>
	<artifactId>springfox-swagger-ui</artifactId>
	<version>2.9.2</version>
</dependency>

2)启用并配置 Swagger2 功能
  添加一个配置类,专门用于配置 Swagger2 相关功能,这样比较清晰点。通过 @EnableSwagger2 注解开启 Swagger2 功能,通过 @Bean 标注的方法将对 Swagger2 功能的设置放入容器。

@Configuration // 告诉Spring容器,这个类是一个配置类
@EnableSwagger2 // 启用Swagger2功能
public class Swagger2Config {
	/**
	 * 配置Swagger2相关的bean
	 */
	@Bean
	public Docket createRestApi() {
		return new Docket(DocumentationType.SWAGGER_2)
				.apiInfo(apiInfo())
				.select()
				.apis(RequestHandlerSelectors.basePackage("com"))// com包下所有API都交给Swagger2管理
				.paths(PathSelectors.any()).build();
	}

	/**
	 * 此处主要是API文档页面显示信息
	 */
	private ApiInfo apiInfo() {
		return new ApiInfoBuilder()
				.title("演示项目API") // 标题
				.description("学习Swagger2的演示项目") // 描述
				.termsOfServiceUrl("http://www.imooc.com") // 服务网址,一般写公司地址
				.version("1.0") // 版本
				.build();
	}
}

3)使用 Swagger2 进行接口测试
  此时启动项目,然后访问 http://127.0.0.1:8080/swagger-ui.html ,即可打开自动生成的可视化测试页面,如下图。
在这里插入图片描述
Swagger2 自动生成可视化测试界面

  这个页面简单整洁,直接给测试人员使用都很方便。我们以 update 方法为例演示下如何测试。先看看该方法的代码:

/**
 * 修改商品
 */
@PutMapping("/goods/{id}")
public void update(@PathVariable("id") long id, @RequestBody GoodsDo goods) {
	// 修改指定id的商品信息
	goods.setId(id);
	goodsService.editGoods(goods);
}

  测试时先选中对应的方法 update , 然后点击 Try it out 开始测试。
在这里插入图片描述
Swagger2 生成的测试方法

  在参数区域输入 id 和 goods 的值。
在这里插入图片描述
Swagger2 可视化测试参数输入

  点击 Execute 后,返回 Code 为 200 表示 http 请求成功!
在这里插入图片描述
Swagger2 可视化测试结果输出

  由此可见, Swagger2 将接口以可视化的方式呈现出来,开发人员不必手输接口地址、参数名称,就可以发起测试并查看结果,确实非常方便。

  后端人员在开发完成后,可以自己使用 Swagger2 测试下接口可行性。而前端人员也可以打开 Swagger2 网页直接验证接口功能。

4)使用 Swagger2 生成在线 API 文档
  使用 Swagger2 生成在线文档比较简单,直接在控制器方法上添加注解即可。如下:

@Api(tags = "商品API") // 类文档显示内容
@RestController
public class GoodsController {
	@Autowired
	private GoodsService goodsService;
	@ApiOperation(value = "根据id获取商品信息") // 接口文档显示内容
	@GetMapping("/goods/{id}")
	public GoodsDo getOne(@PathVariable("id") long id) {
		return goodsService.getGoodsById(id);
	}
	@ApiOperation(value = "获取商品列表") // 接口文档显示内容
	@GetMapping("/goods")
	public List<GoodsDo> getList() {
		return goodsService.getGoodsList();
	}
	@ApiOperation(value = "新增商品") // 接口文档显示内容
	@PostMapping("/goods")
	public void add(@RequestBody GoodsDo goods) {
		goodsService.addGoods(goods);
	}
	@ApiOperation(value = "根据id修改商品信息") // 接口文档显示内容
	@PutMapping("/goods/{id}")
	public void update(@PathVariable("id") long id, @RequestBody GoodsDo goods) {
		goods.setId(id);
		goodsService.editGoods(goods);
	}
	@ApiOperation(value = "根据id删除商品") // 接口文档显示内容
	@DeleteMapping("/goods/{id}")
	public void delete(@PathVariable("id") long id) {
		goodsService.removeGoods(id);
	}
}

  此时再次打开 http://127.0.0.1:8080/swagger-ui.htm ,会发现相关接口都已经有文字描述了。
在这里插入图片描述

6.3 小结+热部署

  在开发时,可以使用 Swagger2 快速实现测试,并生成在线文档。由于开发阶段经常会修改接口,所以编写纸质文档实在是劳民伤财。如果使用 Swagger2 ,重启 Spring Boot 后刷新页面,就能看到最新 API 文档。
  还有一个小技巧,我们可以开启热部署。当我们的代码发生变化时, Spring Boot 会自动重启,这样就省得每次都要手工重启 Spring Boot。

<!-- 引入该依赖即可开启热部署 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
</dependency>

  通过引入依赖,简单配置,就能实现一个非常棒的功能,这就是 Spring Boot 开箱即用的优点体现。

2 Spring Boot 详解配置文件

2.1 前言

  Spring Boot 可以在零配置的情况下使用,但是不代表 Spring Boot 完全不需要配置文件。
  举一个简单的例子, Spring Boot 开发的 Web 项目默认的启动端口是 8080 。如果我们想更换启动端口,通过配置文件去修改是比较好的。如果放到代码中,修改一个端口都要重新编译下程序,岂不烦哉?
  配置文件不是必须的,但是如果想实现一些个性化的功能,还是需要用到配置文件的。本篇就讲下 Spring Boot 中使用配置文件的常用场景。

2.2 构建演示 Web 项目

1)为了便于演示,构建一个 Web 项目。
  创建一个 Spring Boot项目:略
修改 pom.xml
  引入 Web 项目依赖,同时开启热部署便于修改测试。

<!-- 热部署 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- web -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

编写控制器用于测试

@RestController // 标注为控制器,且返回值序列化为json
public class HelloController {
	@GetMapping("/hello") // 响应get请求,匹配的请求路径为/hello
	public Map hello() {
		Map<String, String> map = new HashMap<String, String>();
		map.put("test", "content for test");
		return map;
	}
}

启动项目
  访问 http://127.0.0.1:8080/hello ,效果如下:
在这里插入图片描述
浏览器显示返回数据

2)修改项目启动配置
  运行启动类,启动 spring-boot-profile 应用,控制台会发现如下提示:
  Tomcat started on port(s): 8080 (http) with context path ‘’
  可以看出, Spring Boot 应用默认启动端口是 8080 ,默认项目路径是空。我们可以通过修改 resources/application.properties 来自定义项目启动配置:

# 启动端口
server.port=8000
# 项目路径
server.servlet.context-path=/spring-boot-profile

  再次启动应用,控制台提示变为:
  Tomcat started on port(s): 8000 (http) with context path ‘/spring-boot-profile’
  此时项目对应的访问路径为: http://127.0.0.1:8000/spring-boot-profile , 使用浏览器访问效果如下:
在这里插入图片描述
浏览器显示返回数据

3)配置文件格式
  Spring Boot 支持两种格式的配置文件,即 .properties 文件和 .yml 配置文件。
  上面的配置使用 .yml 则为:

server: 
 port: 8000
 servlet: 
   context-path: /spring-boot-profile

  .properties 配置使用顿号分割语义,而 .yml 配置使用缩进分割语义。这两种配置文件没有本质区别,只是格式不同。

4)自定义配置项
  我们还可以在配置文件中使用自定义配置,例如我们开发了一个微信公众号后台应用,需要在程序中配置公众号的 appid 和 secret 。
  配置文件如下:

# 公众号appid
wxmp.appid=111
# 公众号secret
wxmp.secret=222

  我们定义一个组件,通过 @Value 注解注入配置项的值。

/**
 * 微信公众号参数
 */
@Component//注册为组件
public class WxMpParam {
	@Value("${wxmp.appid}")//注入wxmp.appid配置项
	private String appid;
	@Value("${wxmp.secret}")//注入wxmp.secret配置项
	private String secret;
  //省略get set方法
}

通过控制器测试配置项是否注入成功。

@RestController 
public class HelloController {
	@Autowired
	private WxMpParam wxMpParam;
	@GetMapping("/hello") 
	public Map hello() {
		Map<String, String> map = new HashMap<String, String>();
		map.put("appid",wxMpParam.getAppid());
		map.put("secret",wxMpParam.getSecret());
		return map;
	}
}

  此时我们访问 http://127.0.0.1:8000/spring-boot-profile/hello ,浏览器显示如下,说明配置注入成功。
在这里插入图片描述
浏览器显示返回数据

5)配置项自动注入对象
  如果参数很多,一一指定对象属性和配置项的关联非常麻烦。可以通过设定对象与配置项的对应关系,来实现配置项的自动注入。

@Component // 注册为组件
@EnableConfigurationProperties // 启用配置自动注入功能
@ConfigurationProperties(prefix = "wxmp") // 指定类对应的配置项前缀
public class WxMpParam {
	private String appid;// 对应到wxmp.appid
	private String secret; // 对应到wxmp.secret
  //省略 get set
}

  在上面的代码中,通过 prefix = “wxmp” 指定了关联配置的前缀,属性 appid 即关联到前缀 + 属性名为 wxmp.appid 的配置项。同理,属性 secret 关联到 wxmp.secret 配置项。

6)在配置文件中使用随机数
  配置文件中使用随机数也是比较常见的场景,尤其启动多个客户端时,希望指定一个启动端口的范围,例如 10 - 20 ,可配置如下:

# 配置端口为1-20间的随机数
server.port=${random.int[10,20]}

  这样可以连续启动四个客户端,启动端口分别是 12 、 13 、 17 、 19 ,可见是随机的,而且在指定的范围内波动。

7)自定义配置文件
  有时候参数太多,都放到一个配置文件中太乱了,我们会希望将配置分到不同文件中,然后每个文件保存不同配置。
  例如上面微信公众号配置,我们单独建立一个 wxmp.properties 文件,内容如下:

# wxmp.properties配置文件
# 公众号的appid
wxmp.appid=111
# 公众号的secret
wxmp.secret=222

WxMpParam 代码如下:

/**
* 微信公众号参数
*/
@Component // 注册为组件
@PropertySource(value = "classpath:wxmp.properties", encoding = "utf-8") // 指定配置文件及编码
public class WxMpParam {
   @Value("${wxmp.appid}")
   private String appid;
   @Value("${wxmp.secret}")
   private String secret;
}

8)配置项引用
  Spring Boot 配置项是可以引用其他配置项的值的,例如:

# wxmp.properties
# 公众号的appid
wxmp.appid=111
# 公众号的secret,值为111222
wxmp.secret=${wxmp.appid}222

2.3 小结

对一个 Spring Boot 应用而言:
  如果配置项比较少,直接全部写在 application.properties 。
  如果配置项很多,可以划分为若干配置文件。
  如果很多自定义配置拥有相同的前缀,可以指定前缀,让配置项自动注入对象中。

3 Spring Boot 跨域与前后端分离

3.1 前言

  目前,使用 Spring Boot 进行前后端分离项目开发是主流做法。这种方式,在开发、测试阶段,都比较方便。
  开发阶段,项目组定义好接口规范后,前端按规范开发前端页面,后端按规范编写后端接口,职责分明。
  测试阶段,后端是独立项目,可以进行单元测试。前端可以随时使用最新版本的后端程序进行实际测试。
  前后端分离的模式,有着很多的优越性,所以造就了它的流行。

3.2 技术选型

  本篇通过商品浏览项目实例,展现前后端分离项目的开发、测试全流程。
  技术选型方面,后端毫无疑问选择 Spring Boot ,接口风格采用 RESTful 标准。前端则使用简单的 HTML + Bootstrap + jQuery ,并通过 jQuery 的 $.ajax 方法访问后端接口。

3.3 后端开发流程

1)创建一个 Spring Boot 应用:略

2)修改 pom.xml
  引入 Web 项目依赖,开启热部署便于修改测试。

<!-- 热部署 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- web -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

3)定义商品类、商品服务类、商品控制器类
  在控制器类中编写获取商品列表的接口供前端调用。

/**
 * 商品类
 */
public class GoodsDo {
	/**
	 * 商品id
	 */
	private Long id;
	/**
	 * 商品名称
	 */
	private String name;
	/**
	 * 商品价格
	 */
	private String price;
	/**
	 * 商品图片
	 */
	private String pic;
  //省略get set
}

/**
 * 商品服务类
 */
@Service // 注册为服务类
public class GoodsService {
	/**
	 * 获取商品列表
	 */
	public List<GoodsDo> getGoodsList() {
		List<GoodsDo> goodsList = new ArrayList<GoodsDo>();//模拟从数据库查询出的结果返回
		GoodsDo goods = new GoodsDo();
		goods.setId(1L);
		goods.setName("苹果");
		goods.setPic("apple.jpg");
		goods.setPrice("3.5");
		goodsList.add(goods);
		return goodsList;
	}
}

/**
 * 商品控制器类
 */
@RestController
public class GoodsController {
	@Autowired
	private GoodsService goodsService;

	@GetMapping("/goods")//遵循Restful规范的接口
	public List<GoodsDo> getList() {
		return goodsService.getGoodsList();
	}
}

4)启动应用
  访问 http://127.0.0.1:8080/goods ,返回内容如下,可见后端接口已经可用。
在这里插入图片描述
浏览器显示返回数据

3.4 前端开发流程

  前后端分离开发,实际上前端工作就简化了。我们直接新建项目文件夹 shop-front (商城前端项目文件夹),然后将前端页面放到该文件夹即可。
  注意该页面不需要放到 Spring Boot 项目目录下,随便找个目录放置即可。实际开发过程中,后端和前端的项目可能都不在一台计算机上。
  前端核心业务代码如下,由于前端技术不是本节介绍的重点,所以不再详细解释。

  //初始化方法
  $(function () {
    var row = "";
    $.ajax({
      type: "GET",
      url: "http://127.0.0.1:8080/goods", //后端接口地址
      dataType: "json",
      contentType: "application/json; charset=utf-8",
      success: function (res) {
        $.each(res, function (i, v) {
          row = "<tr>";
          row += "<td>" + v.id + "</td>";
          row += "<td>" + v.name + "</td>";
          row += "<td>" + v.price + "</td>";
          row += "<td>" + v.pic + "</td>";
          row += "</tr>";
          $("#goodsTable").append(row);
        });
      },
      error: function (err) {
        console.log(err);
      }
    });
  });

  开发完该页面后,直接使用浏览器双击打开,查看控制台发现有错误信息提示。
在这里插入图片描述
浏览器控制台返回错误信息

  考验英文水平的时候到了!关键是 has been blocked by CORS policy ,意味着被 CORS 策略阻塞了。我们的前端页面请求被 CORS 阻塞了,所以没成功获取到后端接口返回的数据。

3.5 CORS 跨域介绍

  跨域实际上源自浏览器的同源策略,所谓同源,指的是协议、域名、端口都相同的源(域)。浏览器会阻止一个域的 JavaScript 脚本向另一个不同的域发出的请求,这也是为了保护浏览器的安全。
  在上面的例子中,发起请求的网页与请求资源的 URL 协议、域名、端口均不同,所以该请求就被浏览器阻止了。
  CORS 的意思就是跨域资源共享,是一种允许跨域 HTTP 请求的机制,在这种情况下我们就要想办法实现 CORS 跨域了。

3.6 Spring Boot 跨域的实现

  跨域的方法有很多种,我们此处演示一种常用的跨域方法。添加一个配置类,代码如下:

@Configuration//配置类
public class CorsConfig {
	@Bean
	public WebMvcConfigurer corsConfigurer() {
		return new WebMvcConfigurer() {
			@Override
			public void addCorsMappings(CorsRegistry registry) {
				registry.addMapping("/**")//对所有请求路径
				          .allowedOrigins("*")//允许所有域名
				          .allowCredentials(true)//允许cookie等凭证
				          .allowedMethods("GET", "POST", "DELETE", "PUT","PATCH")//允许所有方法
				          .maxAge(3600);  
			}
		};
	}
}

  通过上面的配置类,实现了允许所有对该 Spring Boot 的请求跨域。此时再次打开网页,被跨域策略阻塞的提示消失,界面显示如下:
在这里插入图片描述
浏览器正常显示商品信息

3.7 小结

  一般在项目开发过程中,会先根据功能需求规划页面和后端 API 接口, API 接口往往会形成详细的 API 文档说明。
  后端会快速地开发 API 接口,前期并不会将 API 功能完全实现,而是仅仅返回一些测试值。就像本篇文章中后端接口返回的博客列表,并不是真实从数据库查询出来的,而是构造的测试数据。
  同期,前端可以根据 API 文档,编写前端界面,并调用后端 API 进行测试。
  也就是说,前后端实际上互相不必直接沟通,他们之间的交流是通过 API 文档完成的。由于后端接口往往采用 RESTful 标准规范,所以在理解上并不会存在很多问题。

4 Spring Boot 打包与部署

4.1 操作流程

  我们以上一篇开发的前后端分离项目 spring-boot-cors 为例进行打包、部署演示,步骤如下:
1)服务器运行环境安装
  一般服务器采用 Linux 或者 Windows Server 系统,相对而言 Linux 系统更加稳定安全。实际上 Windows Server 系统对于一般应用来说也足够了,本篇使用 Windows Server 系统进行演示。
  推荐使用云服务器,更加稳定且易于维护,国内厂商阿里云、华为云都还不错。

Tips: 云服务器的硬盘读写性能非常重要,在购买云服务器时务必关注下云硬盘的 IOPS 值(衡量硬盘读写性能的一个指标),一般建议要采用 IOPS > 3800 的云磁盘。

  具备云服务器后,需要安装 JDK 以便运行 Spring Boot 应用。由于 nginx 对静态资源的负载能力非常强悍,所以我们将前端应用部署到 nginx 上。

2)Spring Boot 打包为 jar 并运行
  Spring Boot 应用可以打包为 war 或者 jar ,官方和我个人都是推荐打 jar 包。可以直接运行,无需部署到 Web 服务器上。

  打开命令行工具,进入 spring-boot-cors 项目目录后运行 mvn clean package -Dmaven.test.skip=true 命令,即可快速打包 Spring Boot 应用。
  接下来我们将该应用拷贝至服务器,在同一目录下新建 start.bat 文件,内容如下:
  java -jar spring-boot-cors-0.0.1-SNAPSHOT.jar

  双击 start.bat 文件即可启动项目,效果如下,可以看出系统已经启动成功(started)。
在这里插入图片描述
Spring Boot 打包项目已启动

3)Spring Boot 打包为 war 并运行
  也可以选择将 Spring Boot 打包为 war ,然后放置于 Tomcat 的 webapps 目录下加载运行,接下来我们就详细描述下打包为 war 的过程。

  首先,在 pom.xml 文件中修改默认的打包方式,显式指定打包方式为 war 。

<groupId>com.imooc</groupId>
<artifactId>spring-boot-cors</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-cors</name>
<description>Demo project for Spring Boot</description>
<packaging>war</packaging>

  然后,由于 Spring Boot 内置了 Tomcat ,所以我们在打包时需要排除内置的 Tomcat ,这样可以避免内置 Tomcat 和 war 包部署运行的 Tomcat 产生冲突。在 pom.xml 中添加如下依赖即可:

<!--打war包时排除内置的tomcat-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

  再然后,还需要继承 SpringBootServletInitializer 类并重写 configure 方法,这是为了告诉 Tomcat 当前应用的入口在哪。

@SpringBootApplication
public class SpringBootCorsApplication extends SpringBootServletInitializer {
	@Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(SpringBootCorsApplication.class);
    }
	public static void main(String[] args) {
		SpringApplication.run(SpringBootCorsApplication.class, args);
	}
}

  最后,即可同样使用 mvn clean package -Dmaven.test.skip=true 命令打包应用了,运行命令后会在 target 目录下生成 war 文件,将该文件放置于 Tomcat 的 webapps 目录下运行即可。

4)前端应用部署
  前端应用的部署更加简单,我们直接在云服务器上下载 nginx 然后解压。下载网址 http://nginx.org/en/download.html。
  下载解压后,将前端页面直接放到 nginx/html 目录下即可。当然如果有很多网页,可以先在该目录下建立子目录便于归类网页。
  我们建立 shop-front 目录(表示商城系统的前端项目),然后将网页放入其中,效果如下:
在这里插入图片描述
商城系统前端项目目录内容

  注意还需要修改 goods.html 中访问的后端 URL 地址,假设云服务器的公网 IP 为 x.x.x.x ,则修改为:

$.ajax({
      type: "GET",
      url: "http://x.x.x.x:8080/goods", //后端接口地址
      dataType: "json",
      contentType: "application/json; charset=utf-8",
      success: function (res) {
        $.each(res, function (i, v) {
          row = "<tr>";
          row += "<td>" + v.id + "</td>";
          row += "<td>" + v.name + "</td>";
          row += "<td>" + v.price + "</td>";
          row += "<td>" + v.pic + "</td>";
          row += "</tr>";
          $("#goodsTable").append(row);
        });
      },
      error: function (err) {
        console.log(err);
      }
    });

  此处解释下后端地址 http://x.x.x.x:8080/goods , HTTP 代表协议, x.x.x.x 代表云服务器公网地址, 8080 是我们后端项目的启动端口,由于我们没有在配置文件中设置,所以默认就是 8080 ,最后 goods 是控制器中设定的后端接口路径。
  双击 nginx.exe 启动 nginx ,由于 nginx 默认启动端口是 80 ,所以此时访问 http://x.x.x.x ,效果如下,说明 nginx 启动成功!
在这里插入图片描述
nginx 已启动成功

5)测试
  现在后端 Spring Boot 应用已启动,前端项目也通过 nginx 启动起来。
  在浏览器地址栏打开 http://x.x.x.x/shop-front/goods.html ,效果如下,说明项目全部部署成功。
在这里插入图片描述
项目部署成功后页面显示效果

4.2 小结

  前后端分离部署的方式,更能发挥服务器的性能,如果要进行版本升级,直接替换后端 jar 或者前端项目文件夹即可。

  
ps:以上内容来自对慕课教程的学习与总结

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值