本文共 10507 字,大约阅读时间需要 35 分钟。
Spring Cloud(构建Spring Boot的分布式环境) |Spring Boot(快速构建Spring的应用) |Spring Framework (底层,Java EE框架)
编程语言:Java 8+、Kotlin底层框架:Spring Framework全新特性:Web Flux(传统Spring应用使用标签或注解来描述请求或响应的映射,web flux支持声明式、函数式编程)
函数编程:Java 8 Lambda响应编程:Reactive Streams(java 9 Flow API、Reactive Extensions-RXjava、Reactor)异步编程:Servlet 3.1 或 Asyc NIO
自动装配:MVC、JDBC、事务等组件的装配
内置容器:Tomcat、Jetty等
DevOps:针对生产的开发运维模式
- 编写 Rest 程序
- 运行 Spring Boot 应用
- 使用 HTTP 请求工具:PostMan
- 场景说明:
- 定义用户模型,包括属性:用户ID和名称
- 客户端发送 Post 请求,创建用户 (Web MVC)
- 客户端发送 GET 请求,获取所有用户(Web Flux)
- Map 存储数据
- 网址:
- Project 选择 Maven Project
- Language 选择 Java
- Spring Boot 选择 2以上的版本
- Group 填写:com.test
- Artifact 填写:first-app-demo
- Depencies 填写:Reactive Web
- 点击 Generate Project 下载项目
package com.test.firstappdemo.domain;/** * * 用户模型 * */public class User { 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; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; }}
package com.test.firstappdemo.repository;import com.test.firstappdemo.domain.User;import org.springframework.stereotype.Repository;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import java.util.concurrent.atomic.AtomicInteger;/** * {@link User} {@link @Repository} * */@Repositorypublic class UserRepository { //内存型保存方式 private final ConcurrentMapuserRepostory = new ConcurrentHashMap<>(); private final static AtomicInteger idGenerator = new AtomicInteger(); /** * 保存对象 * @param user {@link User} 对象 * @return 如果保存成功,返回 true
* 否则,返回false
* */ public boolean save(User user){ //从1开始 Integer id = idGenerator.incrementAndGet(); user.setId(id); return userRepostory.put(id, user) == null; }}
package com.test.firstappdemo.controller;import com.test.firstappdemo.domain.User;import com.test.firstappdemo.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class UserController { // 注入用户仓储,构造器注入好处:不能修改,提前初始化 private UserRepository userRepository; @Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } @PostMapping("/person/save") public User save(@RequestParam String name){ User user = new User(); user.setName(name); if(userRepository.save(user)){ System.out.printf("用户对象:%s 保存成功.\n", user); } return user; }}
启动类名称:<项目名称+Application>,debug启动(启动后可查看Spring Boot版本和PID,web flux默认使用Netty容器进行启动)
PostMan:POST请求 【http://localhost:8080/person/save】 ;属性设置 name=zcheng
package com.test.firstappdemo.repository;import com.test.firstappdemo.domain.User;import org.springframework.stereotype.Repository;import java.util.Collection;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;import java.util.concurrent.atomic.AtomicInteger;/** * {@link User} {@link @Repository} * */@Repositorypublic class UserRepository { //内存型保存方式 private final ConcurrentMapuserRepostory = new ConcurrentHashMap<>(); private final static AtomicInteger idGenerator = new AtomicInteger(); /** * 保存对象 * @param user {@link User} 对象 * @return 如果保存成功,返回 true
* 否则,返回false
* */ public boolean save(User user){ //从1开始 Integer id = idGenerator.incrementAndGet(); user.setId(id); return userRepostory.put(id, user) == null; } public Collectionvalues() { return userRepostory.values(); }}
package com.test.firstappdemo.controller;import com.test.firstappdemo.domain.User;import com.test.firstappdemo.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.Collection;@RestControllerpublic class UserController { // 注入用户仓储,构造器注入好处:不能修改,提前初始化 private UserRepository userRepository; @Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } @PostMapping("/person/save") public User save(@RequestParam String name){ User user = new User(); user.setName(name); if(userRepository.save(user)){ System.out.printf("用户对象:%s 保存成功.\n", user); } return user; } @GetMapping("/person/findAll") public CollectionfindAll(){ return userRepository.values(); }}
package com.test.firstappdemo.config;import com.test.firstappdemo.domain.User;import com.test.firstappdemo.repository.UserRepository;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.reactive.function.server.RequestPredicates;import org.springframework.web.reactive.function.server.RouterFunction;import org.springframework.web.reactive.function.server.RouterFunctions;import org.springframework.web.reactive.function.server.ServerResponse;import reactor.core.publisher.Flux;import reactor.core.publisher.Mono;import java.util.Collection;/** * 路由器函数 * *///从Spring 3开始逐渐使用Configuration代替xml文件@Configurationpublic class RouterFunctionConfiguration { /** * Servlet: * 请求接口:ServletRequest 或者 HttpServletRequest * 响应接口:ServletResponse 或者 HttpServletResponse * Spring 5.0 重新定义了服务的请求和响应: * 请求接口:ServerRequest * 响应接口:ServerResponse * 请求和响应接口既支持Servlet的规范,也可以自定义规范,比如:Netty(Web Server) * Reactive中的Flux 或 Mono 它是异步处理(非阻塞) * 集合对象基本上是同步处理(阻塞) * Flux 或 Mono 都是 Publisher(发布者)推模式来推送数据 * Web Flux通过异步的方式提高吞吐量 * 1.5 Functional Endpoints 介绍函数式的端点(Rest暴露) * 1.5.2 RouterFunction 查看例子 * */ /** * 场景: * 定义GET请求,并且返回所有的用户对象 URL:/person/find/all * 依赖仓储对象,@Autowired 可以不加,只是表明 仓储是方法注入 * * */ @Bean @Autowired public RouterFunctionpersonFindAll(UserRepository userRepository){ // 定义映射关系,一般s结尾都是静态类或工具类,lamda表达式,request是方法参数 // HandlerFunction参数是ServerRequest,返回Mono return RouterFunctions.route(RequestPredicates.GET("/person/find/all"), request -> { // 获取所有对象 Collection users = userRepository.values(); //集合对象转Flux对象 Flux userFlux = Flux.fromIterable(users); return ServerResponse.ok().body(userFlux, User.class); }); }}
Apache Maven官网:http://maven.apache.org/archetype/maven-archetype-plugin/generate-mojo.html
// interactiveMode=false表示非交互式
Windows -> CMD窗口:mvn archetype:generate -DinteractiveMode=false -DgroupId=com.test -DartifactId=first-app-demo -Dversion=1.0.0-SNAPSHOT
// 查看文件目录
$ dir
https://spring.io/guides/gs/rest-service/ 找到 Build with Maven,复制 pom.xml 配置
// IDEA 弹窗 Enable Auto Import
// 默认生成的jUnit测试工具,去掉版本号,因为Spring的父工程中已经存在版本控制
然后配置启动类和控制类,和之前的内容一样
调整主(父)工程(由jar变为子项目的管理)
创建子模块工程()
模块层:model(domain)
持久层:presistence(repository)
表示层:web(controller)
子模块依赖管理()
修改pom.xml(有可能最后删除src时,IDEA会自动添加,所以这一步可以尝试忽略)
pom
创建 maven 子模块
a. web -> presistence -> model 由高往低创建
b. 项目名称 -> New -> Module -> 不选择archetype -> artifactId填写 web -> Finish
c. 如果web的src中java和resources未标记文件夹类型(没问题的直接跳过)
- java 文件夹 -> 右键 -> Mark Directory as -> Sources Root
- resources 文件夹 -> 右键 -> Mark Directory as -> Resources Root
- test 文件夹 -> 右键 -> Mark Directory as -> Test Sources Root
d. 迁移代码
子模块创建 java 文件夹创建 com.test(这一步要看IDEA版本给不给直接拖到)
选择父项目的 java 下的内容 com.xxx.xxx 拖到 web 子模块的 java文件夹中
Move everything from
Yes -> Continue
选择父项目的 resources 下的内容,拖到 web 子模块的 resources文件夹中
删除父项目的src文件夹
运行启动类
接下来根据上面步骤,把其它子模块也进行重构
presistence pom.xml 设置 model 依赖;复制model pom.xml
web pom.xml 设置 presistence 依赖;复制presistence pom.xml
IDEA 头部菜单 -> Build -> Build Project -> 运行启动类
- 构建 JAR 包
- 构建 WAR 包
- 构建 Main-Class
父pom.xml文件添加main-class:(进入启动类 -> 选中类名右键 -> copy Reference)
org.springframework.boot spring-boot-maven-plugin com.test.firstappdemo.FirstAppDemoApplication
将上面父pom.xml 内容剪切到web子模块的pom.xml中
// 跳过测试,更新第三方包
cmd窗口(IDEA Terminal):项目名称 -> 右键 -> copy path -> cd 项目路径 -> mvn -Dmaven.test.skip -U clean package
或者 使用IDEA右侧菜单的Maven Projects的LifeCycle
cmd窗口(IDEA Terminal):cd web -> cd target -> java -jar web-0.0.1-SNAPSHOT.jar
web子模块添加目录 src/main/webapp/WEB-INF/web.xml
web pom.xml文件新增或修改
// 默认jar
war
cmd窗口(IDEA Terminal):cd web -> cd target -> java -jar web-0.0.1-SNAPSHOT.war
cmd窗口(IDEA Terminal):项目根目录 -> mvn -Dmaven.test.skip -U clean install
cmd窗口(IDEA Terminal):cd web -> mvn spring-boot:run
转载地址:http://zknws.baihongyu.com/