和阿若分手后,我写了一个小站

623 阅读3分钟

和阿若分手也有一段时间了,最近每晚做梦都是她的样子,所以我想把这份思念放开。

前端技术不佳,再者已有一年多未使用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;
}
后话

爱情里的关键时机,错过了,你就错过了那个人。