问题:系统参数是什么
每学期给学生生成跑步任务,跑步成绩计算。
小程序上报的问题,跑一千米只有700米类似。
dev 测试
local 生产
1. 背景
杨老师希望我接受这个项目,并且能全部理解并加以开发和修改
我自己也可以通过学习这个项目来增长自己的能力。
2. 项目介绍
项目是标准的企业级spring cloud项目,包含多个服务,代码量大。
3. 服务学习
3.1. auth:认证服务
3.1.1. aspect包
其中进行切片编程,简而言之:当你调用distributeResources2Role的时候会自动异步调用refreshRoleResourceCache方法。
@Aspect
@Component
public class RoleResourceCacheAop {
@Autowired
private RoleService roleService;
// 定义切入点,即监听distributeResources2Role方法
@Pointcut("execution(public * com.onesports.service.auth.web.RoleController.distributeResources2Role(..))")
public void roleResourceUpdate() {
}
// 在调用distributeResources2Role的时候,将返回值作为ret,开启线程异步调用refreshRoleResourceCache方法
@AfterReturning(returning = "ret", pointcut = "roleResourceUpdate()")
public void doAfter(Object ret) {
Thread thread = new Thread(() -> roleService.refreshRoleResourceCache());
thread.start();
}
}
3.1.2. client包
其中包含一个接口文件,作为定时任务在quartzJob包中实现。
3.1.3. config包
配置了 redis 和 swagger
redis 配置了RedisCacheManager 比 redisTemplate 更高一层的抽象
3.1.4. database包
存储了一个数据库文件,具体是什么没有仔细看
3.1.5. model包
包含在服务中需要用到的request对象 response对象等
3.1.6. quartzJob包
其中基于quartz框架进行了对定时任务增删改查的封装
重写了executeInternal 方法,后续可以使用这个组件来调用这个定时方法
@Component("overNightJob")
@Slf4j
public class OverNightJob extends QuartzJobBean {
@Autowired
BusinessClient businessClient;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("定时任务触发");
businessClient.doOverNightJob();
}
}
3.1.7. repository包
其中定义了多个JPA用到的对数据库增删改查的类
3.1.8. resource包
其中定义了保存系统日志的api和获取系统参数的api
3.1.9. service包
- AuthStartupRunner:在服务启动后更新role 的缓存。
- 实现了CommandLineRunner接口,重写run方法。服务启动后会调用run
- ApplicationRunner 和 CommandLineRunner都有run方法,都会在应用启动后直接调用,CommandLineRunner接收简单的命令行参数,ApplicationRunner接收的参数更为复杂。
- OverNightBacthRunner
- 在应用运行之后实现调用定时任务OverNight任务
- 其他文件,定义了服务需要的接口:比如user,resource,param等
3.1.10. validator包
- 实现了一个ModifyUserRequestValidator类
- 实现了Validator接口,其中support方法判断类型是否兼容,validate方法实现鉴权的部分
@Component("modifyUserRequestValidator")
public class ModifyUserRequestValidator implements Validator {
@Autowired
UserRepository userRepository;
@Autowired
private MessageSource messageSource;
// 这个validator 兼容ModifyUserRequest和其父类
@Override
public boolean supports(Class<?> aClass) {
return ModifyUserRequest.class.isAssignableFrom(aClass);
}
@Override
public void validate(@Nullable Object target, Errors errors) {
if (errors.hasErrors()) {
return;
}
if (Objects.isNull(target)) {
return;
}
ModifyUserRequest request = (ModifyUserRequest) target;
if (!userRepository.existsById(request.getId())) {
errors.reject("id", messageSource.getMessage("用户不存在", null, Locale.CHINA));
}
}
}
validator会在之后被显式调用
3.1.11. web包
提供了多个服务的接口
- 批处理信息
- 校园信息
- 机构信息
- 日志信息
- 登录操作管理
- 参数管理
- 系统资源管理
- 角色分配资源管理
- 用户信息管理
3.2. base-data服务
3.2.1. client包
提供两个接口
- sessionsIsExistByPlaceId:根据场地id查询判断场次是否存在
- deleteUploadFileByIds:根据文件id链删除文件
3.2.2. config包
swagger
ModelMapper配置:ModelMapper是简化配置对象映射的类,这里配置了对象之间的匹配策略是LOOSE(宽松)
以下是几种常用的匹配策略:
MatchingStrategies.STRICT
:严格匹配策略,要求源对象和目标对象的字段名完全一致,包括大小写。MatchingStrategies.LOOSE
:宽松匹配策略,允许源对象和目标对象的字段名有一定的差异,例如大小写不一致或者使用了下划线命名。MatchingStrategies.STANDARD
:默认的标准匹配策略,与严格匹配策略相同,要求字段名完全一致。
3.2.3. model包
3.2.4. repository包
3.2.5. service包
提供了多个接口
- 闸机信息管理
- 人脸信息管理
- 商户信息管理
- 营业点信息管理
- 场区信息管理
- 场馆信息管理
- 运动类型信息管理
- 系统参数
3.2.6. web包
与service包基本一致
3.3. business服务:主要的业务
3.4. common服务 字典类
3.4.1. config包
swagger
3.4.2. model包
3.4.3. resource包
实现一个WebMessageResource类
这个类 实现对消息的管理还包含了对字典数据的查询
3.4.4. service包
提供了多个接口
- 序列号自增
- 字典删除
- 提醒信息操作
- 文件上传操作
3.4.5. web包
提供service中的api
3.5. common-core
3.5.1. annotation包:创建注解ExcelAnno
这个注解标记用来在导出excel操作的类的字段
import java.lang.annotation.*;
// 这个注解用在字段上,是运行时也需要的注解,可被继承
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ExcelAnno {
/**
* 在excel文件中某列数据的名称
*
* @return 名称
*/
String cellName() default "";
/**
* 在excel对应的列
*
* @return
*/
String excelCol() default "";
/**
* 实体中的字段类型
*
* @return
*/
FieldDataType fieldDataType() default FieldDataType.STRING;
/**
* 案件导入时对应的数据类型
*
* @return
*/
FieldType fieldType() default FieldType.CASE;
/**
* 是否必输
*
* @return
*/
FieldInput fieldInput() default FieldInput.NO;
/**
* 实体中的字段类型枚举
*/
enum FieldDataType {
STRING,
INTEGER,
DOUBLE,
DATE,
DATETIME,
BIGDICIMAL,
PERCENT,
ENUM,
LONG
}
/**
* 字段是否必输
*/
enum FieldInput {
YES,
NO
}
/**
* 字段属性类型
*/
enum FieldType {
CASE,
CONTRACT,
PERSONAL,
PERSONAL_HOUSE,
PERSONAL_INCOME,
PERSONAL_CONTACT,
PRODUCT,
PRODUCT_SERIES,
PERSONAL_JOB
}
}
3.5.2. config包
- baseconfig
- setHeaderToken:设置了接收参数token,请求头参数,是非必须的
@Configuration
public class BaseConfig {
public List<Parameter> setHeaderToken() {
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name("X-UserToken").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
return pars;
}
}
- redisconfig
- webconfig
- 添加了一个参数处理器LoginUserMethodArgumentResolver,用来判断前端传递的参数是否包含token
- configureMessageConverters方法:将参数中的Long类型转化成字符串。
- addResourceHandler:将静态资源的path定向到某个目录
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
private static final Logger logger = LoggerFactory.getLogger(WebConfig.class);
@Autowired
private RequestMappingHandlerAdapter handlerAdapter;
// 添加一个参数解析控制器,判断请求头是否包含token
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(currentUserMethodArgumentResolver());
}
@Bean
public LoginUserMethodArgumentResolver currentUserMethodArgumentResolver() {
return new LoginUserMethodArgumentResolver();
}
// 将参数中的Long类型转化成String
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
converters.add(jackson2HttpMessageConverter);
}
// 将静态资源重定向到目录下
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
// 这个是参数解析判断token的代码
public class LoginUserMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private RedisTemplate<String, UserModel> operatorTokenRedisTemplate;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.getParameterType().isAssignableFrom(UserModel.class);
}
@Override
public Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
String accessToken = webRequest.getHeader("X-UserToken");
UserModel userModel = null;
if (isBlank(accessToken) ||
null == (userModel = operatorTokenRedisTemplate.opsForValue().get("TOKEN:" + accessToken))) {
throw new BadRequestException(null, this.getClass().getSimpleName(), "{403}当前请求需要用户登录");
}
return userModel;
}
}
3.5.3. enum包
包含多个枚举类,所有的常量都在这里
3.5.4. expetion包
包含一个自定义的BadRequestException类,继承RuntimeException
3.5.5. jpa包
实现一个雪花id生成api,继承IdentifierGenerator
3.5.6. model包
3.5.7. utils包
各种工具类
3.5.8. web包
包含
- exception处理
- 使用Mysql查询请求的基类
- 使用BigDecimal序列化钱的数字
- 切片记录日志,所有接口调用的时间等
3.6. data-sync服务:将本地和远程的数据库表进行同步
3.6.1. config包
- MybatisPlusConfig:动态表,分页,乐观锁等插件配置
- MyTableNameHandler:动态表名,将表名和后缀存储在两个线程中,然后对表名进行重新构建
3.6.2. domain包
表信息,存放表名及建表sql
3.6.3. mapper包
存放了LocalMapper和RemoteMapper:
- Mapper层,负责数据库查询
- 使用DS注解,切换数据源为local或者remote
3.6.4. service包
实现了本地和远程数据库的对表的操作的接口
3.6.5. task包
实现将本地和远程数据库同步,将本地表推送给远程
3.7. entity:实体类服务
在这个服务中定义所有的实体类,分不同服务进行定义
3.8. Eureka:注册中心
3.9. exercise:运动服务
3.9.1. client包
3.10. gateway:网关服务
提供了拦截器,拦截请求,判断token
3.11. message:消息服务
3.11.1. config包
- ApplicationContextConfig:通过name获取bean,通过class获取bean,通过name calzz获取bean
- MessageSocketServer:向在线的用户推送消息
3.12. system-docking:闸机服务
3.12.1. config包
- tomcat配置:更改tomcat的协议
- CAS(单点登录)配置:
@Configuration
public class CasFilterConfig {
/**
* 需要走cas拦截的地址(/* 所有地址都拦截)
*/
private final static String URL_PATTERN = "/api/docking/getLoginUserInfo";
/**
* 默认的cas地址,防止通过 配置信息获取不到
*/
@Value("${cas.server-url-prefix}")
private String casServerUrlPrefix;
/**
* 默认的cas地址,防止通过 配置信息获取不到
*/
@Value("${cas.server-login-url}")
private String casServerLoginUrl;
/**
* 应用访问地址(这个地址需要在cas服务端进行配置)
*/
@Value("${cas.client-host-url}")
private String casClientHostUrl;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public ServletListenerRegistrationBean servletListenerRegistrationBean() {
ServletListenerRegistrationBean listenerRegistrationBean = new ServletListenerRegistrationBean();
listenerRegistrationBean.setListener(new SingleSignOutHttpSessionListener());
listenerRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return listenerRegistrationBean;
}
/**
* 单点登录退出
*
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean singleSignOutFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new SingleSignOutFilter());
registrationBean.addUrlPatterns(URL_PATTERN);
registrationBean.addInitParameter("casServerUrlPrefix", casServerUrlPrefix);
registrationBean.setName("CAS Single Sign Out Filter");
registrationBean.setOrder(2);
return registrationBean;
}
/**
* 单点登录认证
*
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean AuthenticationFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new AuthenticationFilter());
registrationBean.addUrlPatterns(URL_PATTERN);
registrationBean.setName("CAS Filter");
registrationBean.addInitParameter("casServerLoginUrl", casServerLoginUrl);
registrationBean.addInitParameter("serverName", casClientHostUrl);
registrationBean.setOrder(3);
return registrationBean;
}
/**
* 单点登录校验
*
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean Cas30ProxyReceivingTicketValidationFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new Cas30ProxyReceivingTicketValidationFilter());
registrationBean.addUrlPatterns(URL_PATTERN);
registrationBean.setName("CAS Validation Filter");
registrationBean.addInitParameter("casServerUrlPrefix", casServerUrlPrefix);
registrationBean.addInitParameter("serverName", casClientHostUrl);
registrationBean.setOrder(4);
return registrationBean;
}
/**
* 单点登录请求包装
*
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean httpServletRequestWrapperFilter() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(new HttpServletRequestWrapperFilter());
registrationBean.addUrlPatterns(URL_PATTERN);
registrationBean.setName("CAS HttpServletRequest Wrapper Filter");
registrationBean.setOrder(5);
return registrationBean;
}
}
- fastjson配置:确定了string和json的转化规则
- swagger
3.12.2. schedule包
定时任务:同步人脸信息
3.13. membercard服务
3.13.1. config包
- druid配置:druid是一个高性能的数据库处理池。
3.14. wechat服务
4. 业务api调用(从前端查看)
4.1. 管理端(主要是exercise服务,包含个别business和auth服务)
- 课外运动跟踪:
- queryRequireInfoByStatus
- queryFacultyClassTree
- 课外运动计划:
- queryPlanInfoByPage
- 课外运动成绩
- queryParentClassList
- queryAllAcademicYear
- queryFacultyClassList
- queryTaskInfo
- 运营中心
- queryPlanInfoByTeacherId
- getAnnouncementTypeNum
- getAnnouncementByPage
- querySafetyTipsPhoto
- 基础数据管理
- queryMotionClass
- queryPlanInfoByTeacherId
- queryAcademicYear
- querySunTeacherInfo
- queryConfigurationSportsTeacherInfo
- queryRunningArea
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 2738430398@qq.com