仿12306系统学习
学习路线
12306 铁路购票系统学习总体分为三块:组件库开发、业务梳理以及业务系统开发。

组件库开发
组件库的产出源于对公共功能的封装,避免了在不同项目之间相互复制代码的情况。当然,如果这种复制代码的方式出现问题,那么需要同时对所有项目进行改造,从成本和优雅设计的角度来看并不可取。
为了统一各个项目可能使用的公共内容,我们在这里规划了常用且通用的功能点,供大家使用,以提高编码效率。如果有一些好的想法,在通用的前提下,可以联系我们将其加入到各自语义的起始包中。
组件库的开发宗旨是汇总资源,更高效地提供业务敏捷开发的能力,后续的迭代也将遵循这一原则。目前,这只是一个起点,是整体规划的一部分,还有许多可以提升的空间。
目前已有组件如下,可能新增加的组件更新不及时,实际以代码库 /frameworks 目录下为准。

业务梳理
在 12306 铁路购票系统中,包括会员、购票、订单、支付以及网关服务。

GatewayServiceApplication<网关服务>
自定义局部过滤器
/**
 * SpringCloud Gateway Token 拦截器
 *
 * @公众号:马丁玩编程,回复:加群,添加马哥微信(备注:12306)获取项目资料
 */
@Component
public class TokenValidateGatewayFilterFactory extends AbstractGatewayFilterFactory<Config> {
    public TokenValidateGatewayFilterFactory() {
        super(Config.class);
    }
    /**
     * 注销用户时需要传递 Token
     */
    public static final String DELETION_PATH = "/api/user-service/deletion";
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String requestPath = request.getPath().toString();
            if (isPathInBlackPreList(requestPath, config.getBlackPathPre())) {
                String token = request.getHeaders().getFirst("Authorization");
                // TODO 需要验证 Token 是否有效,有可能用户注销了账户,但是 Token 有效期还未过
                UserInfoDTO userInfo = JWTUtil.parseJwtToken(token);
                if (!validateToken(userInfo)) {
                    ServerHttpResponse response = exchange.getResponse();
                    response.setStatusCode(HttpStatus.UNAUTHORIZED);
                    return response.setComplete();
                }
                ServerHttpRequest.Builder builder = exchange.getRequest().mutate().headers(httpHeaders -> {
                    httpHeaders.set(UserConstant.USER_ID_KEY, userInfo.getUserId());
                    httpHeaders.set(UserConstant.USER_NAME_KEY, userInfo.getUsername());
                    httpHeaders.set(UserConstant.REAL_NAME_KEY, URLEncoder.encode(userInfo.getRealName(), StandardCharsets.UTF_8));
                    if (Objects.equals(requestPath, DELETION_PATH)) {
                        httpHeaders.set(UserConstant.USER_TOKEN_KEY, token);
                    }
                });
                return chain.filter(exchange.mutate().request(builder.build()).build());
            }
            return chain.filter(exchange);
        };
    }
    private boolean isPathInBlackPreList(String requestPath, List<String> blackPathPre) {
        if (CollectionUtils.isEmpty(blackPathPre)) {
            return false;
        }
        return blackPathPre.stream().anyMatch(requestPath::startsWith);
    }
    private boolean validateToken(UserInfoDTO userInfo) {
        return userInfo != null;
    }
}
Gateway 分类:局部过滤器和全局过滤器。
- 局部过滤器(GatewayFilter):应用到单个路由或者一个分组的路由上。
- 全局过滤器(GlobalFilter):应用到所有的路由上。




![[SQL开发笔记]IN操作符: 在WHERE子句中规定多个值](https://img-blog.csdnimg.cn/61963ae9ac534502af20a6d98f5c72cf.png)











![2023年中国临床决策支持系统发展趋势分析:综合性决策系统将成市场主流[图]](https://img-blog.csdnimg.cn/img_convert/bcd9efd3aa6f9596baa5cb6e5ec7102a.png)


