和阿若分手也有一段时间了,最近每晚做梦都是她的样子,所以我想把这份思念放开。
前端技术不佳,再者已有一年多未使用Jquery和bootstrap,本次用spring webflux 技术实现了小站的小功能
主要技术: JDK11,Spring,Spring WebFlux,Mongo,Vue ,BootStrap
小站访问地址:j2boot.com/walls/
以下只做部分技术摘要
导入依赖
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<!--响应式mongo依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
创建持久化对象
@Data
@Builder
@Document(collection = "walls_content")
@AllArgsConstructor
@NoArgsConstructor
public class ContentBean implements Serializable {
@Id
private String id;
private Long createTime;
private String content;
private String createNick;
private String ip;
private Boolean deleted;
}
移除mongo中_class列,否则创建文档时候会带有class属性
@Configuration
public class MongoConfig implements InitializingBean{
@Autowired
@Lazy
private MappingMongoConverter mappingMongoConverter;
@Override
public void afterPropertiesSet() {
mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
}
}
建立服务器统一响应码,不做过多解释
/**
* @author 易成贤
* @Description TODO
* @Date 2020/7/22 14:58
**/
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult<T> implements Serializable {
/**
* 响应码
*/
private int code;
/**
* 是否成功
*/
private boolean success;
/**
* 响应消息
*/
private String message;
/**
* 响应数据
*/
private T data;
/**
* 响应时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime time;
public ApiResult() {
time = LocalDateTime.now();
}
public static ApiResult<Boolean> result(boolean flag) {
if (flag) {
return ok();
}
return fail();
}
public static ApiResult<Boolean> result(ApiCode apiCode) {
return result(apiCode, null);
}
public static <T> ApiResult<T> result(ApiCode apiCode, T data) {
return result(apiCode, null, data);
}
public static <T> ApiResult<T> result(ApiCode apiCode, String message, T data) {
boolean success = false;
if (apiCode.getCode() == ApiCode.SUCCESS.getCode()) {
success = true;
}
String apiMessage = apiCode.getMessage();
if (StrUtil.isNotBlank(apiMessage)) {
message = apiMessage;
}
return (ApiResult<T>) ApiResult.builder()
.code(apiCode.getCode())
.message(message)
.data(data)
.success(success)
.time(LocalDateTime.now())
.build();
}
public static ApiResult<Boolean> ok() {
return ok(null);
}
public static <T> ApiResult<T> ok(T data) {
return result(ApiCode.SUCCESS, data);
}
public static <T> ApiResult<T> ok(T data, String message) {
return result(ApiCode.SUCCESS, message, data);
}
public static ApiResult<Map<String, Object>> okMap(String key, Object value) {
Map<String, Object> map = new HashMap<>(1);
map.put(key, value);
return ok(map);
}
public static ApiResult<Boolean> fail(ApiCode apiCode) {
return result(apiCode, null);
}
public static ApiResult<String> fail(String message) {
return result(ApiCode.FAIL, message, null);
}
public static <T> ApiResult<T> fail(ApiCode apiCode, T data) {
if (ApiCode.SUCCESS == apiCode) {
throw new RuntimeException("失败结果状态码不能为:" + ApiCode.SUCCESS.getCode());
}
return result(apiCode, data);
}
public static ApiResult<String> fail(Integer errorCode, String message) {
return new ApiResult<String>()
.setSuccess(false)
.setCode(errorCode)
.setMessage(message);
}
public static ApiResult<Map<String, Object>> fail(String key, Object value) {
Map<String, Object> map = new HashMap<>(1);
map.put(key, value);
return result(ApiCode.FAIL, map);
}
public static ApiResult<Boolean> fail() {
return fail(ApiCode.FAIL);
}
}
/**
* @author 易成贤
* @Description TODO
* @Date 2020/7/22 14:57
**/
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum ApiCode {
/**
* 操作成功
**/
SUCCESS(200, "操作成功"),
/**
* 非法访问
**/
UNAUTHORIZED(401, "非法访问"),
/**
* 没有权限
**/
NOT_PERMISSION(403, "没有权限"),
/**
* 你请求的资源不存在
**/
NOT_FOUND(404, "你请求的资源不存在"),
/**
* 操作失败
**/
FAIL(500, "操作失败"),
/**
* 系统异常
**/
SYSTEM_EXCEPTION(5000, "系统异常"),
;
private final int code;
private final String message;
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
}
Controller层
@RestController
@RequestMapping("content")
public class WallsController {
@Autowired
private WallsService wallsService;
/**
* @return
*/
@GetMapping(value = "/findContent")
public Mono<ApiResult<WallsContentVo>> findWallsContent() {
Mono<ApiResult<WallsContentVo>> content = wallsService.findOneWallsContent();
return content;
}
/**
* @return
*/
@PostMapping(value = "/addContent")
public Mono<ApiResult> addWallsContent(@RequestBody @Validated ReWallsContentVo reWallsContentVo, ServerWebExchange exchange) {
String ip = exchange.getRequest().getRemoteAddress().getAddress().toString().replaceAll("/","");
return wallsService.addWallsContent(reWallsContentVo, ip);
}
}
Service层
/**
* @author 易成贤
* @Description TODO
* @Date 2020/7/22 15:22
**/
public interface WallsService {
/**
* 随机查询一个内容
* @return
*/
Mono<ApiResult<WallsContentVo>> findOneWallsContent();
/**
*
* @param reWallsContentVo
* @param ip
* @return
*/
Mono<ApiResult> addWallsContent(ReWallsContentVo reWallsContentVo, String ip);
}
/**
* @author 易成贤
* @Description TODO
* @Date 2020/7/22 15:22
**/
@Service
public class WallsServiceImpl implements WallsService {
@Resource
private ReactiveMongoTemplate mongoTemplate;
@Autowired
private RegionSearcher regionSearcher;
/**
* 随机查询一个内容
*
* @return
*/
@Override
public Mono<ApiResult<WallsContentVo>> findOneWallsContent() {
Criteria criteria = Criteria.where("deleted").is(false);
return mongoTemplate.aggregate(
Aggregation.newAggregation(
Aggregation.match(criteria),
//随机采样
Aggregation.sample(1)
),
//查询的
ContentBean.class,
//返回的
ContentBean.class
).next().timeout(Duration.ofSeconds(4))
.onErrorReturn(ContentBean.builder().content("抱歉,可能出了点小问题").ip("0").createTime(System.currentTimeMillis()).createNick("系统").build()).map(
bean -> ApiResult.ok(WallsContentVo.builder()
.content(bean.getContent())
.createNick(bean.getCreateNick())
.build())
);
}
/**
* @param reWallsContentVo
* @param ip
* @return
*/
@Override
public Mono<ApiResult> addWallsContent(ReWallsContentVo reWallsContentVo, String ip) {
if (StrUtil.isBlank(ip)) ip = "0";
ContentBean bean = ContentBean.builder().createTime(System.currentTimeMillis())
.content(reWallsContentVo.getContent()).createNick(reWallsContentVo.getCreateNick()).deleted(false).ip(ip).build();
return mongoTemplate.insert(bean).timeout(Duration.ofSeconds(4)).map(
val -> ApiResult.ok()
);
}
返回的view object 摘要
/**
* @author 易成贤
* @Description TODO
* @Date 2020/7/22 15:31
**/
@Data
@Builder
public class WallsContentVo implements Serializable {
private String content;
private String createNick;
private String position;
}
后话
爱情里的关键时机,错过了,你就错过了那个人。