"vscode:/vscode.git/clone" did not exist on "06ad056fa06c930b995a1bfaad6f697cf4d6a955"
Commit de3de82d authored by dingzhiwei's avatar dingzhiwei
Browse files

初始化Jeepay项目

parent 40dcaf4a
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.mq.queue;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* 更新商户配置mq
*
* @author pangxiaoyu
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Slf4j
@Component
public class MqQueue4ModifyMchUserRemove extends ActiveMQQueue {
public MqQueue4ModifyMchUserRemove(){
super(CS.MQ.QUEUE_MODIFY_MCH_USER_REMOVE);
}
/**
* @author: pangxiaoyu
* @date: 2021/6/7 16:17
* @describe: 接收 更新系统配置项的消息
*/
@JmsListener(destination = CS.MQ.QUEUE_MODIFY_MCH_USER_REMOVE)
public void receive(String userIdStr) {
log.info("成功接收删除商户用户登录的订阅通知, msg={}", userIdStr);
// 字符串转List<Long>
List<Long> userIdList = Arrays.stream(userIdStr.split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
// 删除redis用户缓存
if(userIdList == null || userIdList.isEmpty()){
log.info("用户ID为空");
return ;
}
for (Long sysUserId : userIdList) {
Collection<String> cacheKeyList = RedisUtil.keys(CS.getCacheKeyToken(sysUserId, "*"));
if(cacheKeyList == null || cacheKeyList.isEmpty()){
continue;
}
for (String cacheKey : cacheKeyList) {
// 删除用户Redis信息
RedisUtil.del(cacheKey);
continue;
}
}
log.info("无权限登录用户信息已清除");
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.mq.topic;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.stereotype.Component;
import javax.jms.ConnectionFactory;
/**
* JMS消息配置项
*
* @author terrfly
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Component
public class JMSConfig {
/** 新增jmsListenerContainer, 用于接收topic类型的消息 **/
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainer(ConnectionFactory factory){
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setPubSubDomain(true);
bean.setConnectionFactory(factory);
return bean;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.mq.topic;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.service.impl.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
/**
* 更新系统配置mq
*
* @author terrfly
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Slf4j
@Component
public class MqTopic4ModifySysConfig extends ActiveMQTopic{
@Autowired private SysConfigService sysConfigService;
public MqTopic4ModifySysConfig(){
super(CS.MQ.TOPIC_MODIFY_SYS_CONFIG);
}
/** 接收 更新系统配置项的消息 **/
@JmsListener(destination = CS.MQ.TOPIC_MODIFY_SYS_CONFIG, containerFactory = "jmsListenerContainer")
public void receive(String msg) {
log.info("成功接收更新系统配置的订阅通知, msg={}", msg);
sysConfigService.initDBConfig(msg);
log.info("系统配置静态属性已重置");
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.secruity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
/*
* 用户身份认证失败处理类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:11
*/
@Component
public class JeeAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
// This is invoked when user tries to access a secured REST resource without supplying any credentials
// We should just send a 401 Unauthorized response because there is no 'login page' to redirect to
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
//返回json形式的错误信息
// response.setCharacterEncoding("UTF-8");
// response.setContentType("application/json");
// response.getWriter().println("{\"code\":1001, \"msg\":\"Unauthorized\"}");
response.getWriter().flush();
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.secruity;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.jwt.JWTUtils;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.mch.config.SystemYmlConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p><b>Title: </b>JwtAuthenticationTokenFilter.java
* <p><b>Description: </b>
* spring security框架中验证组件的前置过滤器;
* 用于验证token有效期,并放置ContextAuthentication信息,为后续spring security框架验证提供数据;
* 避免使用@Component等bean自动装配注解:@Component会将filter被spring实例化为web容器的全局filter,导致重复过滤。
* @modify terrfly
* @version V1.0
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
* <p>
*/
public class JeeAuthenticationTokenFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
JeeUserDetails jeeUserDetails = commonFilter(request);
if(jeeUserDetails == null){
chain.doFilter(request, response);
return;
}
//将信息放置到Spring-security context中
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(jeeUserDetails, null, jeeUserDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
private JeeUserDetails commonFilter(HttpServletRequest request){
String authToken = request.getHeader(CS.ACCESS_TOKEN_NAME);
if(StringUtils.isEmpty(authToken)){
authToken = request.getParameter(CS.ACCESS_TOKEN_NAME);
}
if(StringUtils.isEmpty(authToken)){
return null; //放行,并交给UsernamePasswordAuthenticationFilter进行验证,返回公共错误信息.
}
JWTPayload jwtPayload = JWTUtils.parseToken(authToken, SpringBeansUtil.getBean(SystemYmlConfig.class).getJwtSecret()); //反解析token信息
//token字符串解析失败
if( jwtPayload == null || StringUtils.isEmpty(jwtPayload.getCacheKey())) {
return null;
}
//根据用户名查找数据库
JeeUserDetails jwtBaseUser = RedisUtil.getObject(jwtPayload.getCacheKey(), JeeUserDetails.class);
if(jwtBaseUser == null){
RedisUtil.del(jwtPayload.getCacheKey());
return null; //数据库查询失败,删除redis
}
//续签时间
RedisUtil.expire(jwtPayload.getCacheKey(), CS.TOKEN_TIME);
return jwtBaseUser;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.secruity;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.entity.SysUserAuth;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.service.impl.SysUserAuthService;
import com.jeequan.jeepay.service.impl.SysUserService;
import com.jeequan.jeepay.core.utils.RegKit;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
/**
* UserDetailsService实现类
*
* @author terrfly
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Service
public class JeeUserDetailsServiceImpl implements UserDetailsService {
@Autowired
private SysUserService sysUserService;
@Autowired
private SysUserAuthService sysUserAuthService;
/**
*
* 此函数为: authenticationManager.authenticate(upToken) 内部调用 ;
* 需返回 用户信息载体 / 用户密码 。
* 用户角色+权限的封装集合 (暂时不查询, 在验证通过后再次查询,避免用户名密码输入有误导致查询资源浪费)
*
* **/
@Override
public UserDetails loadUserByUsername(String loginUsernameStr) throws UsernameNotFoundException {
//登录方式, 默认为账号密码登录
Byte identityType = CS.AUTH_TYPE.LOGIN_USER_NAME;
if(RegKit.isMobile(loginUsernameStr)){
identityType = CS.AUTH_TYPE.TELPHONE; //手机号登录
}
//首先根据登录类型 + 用户名得到 信息
SysUserAuth auth = sysUserAuthService.selectByLogin(loginUsernameStr, identityType, CS.SYS_TYPE.MCH);
if(auth == null){ //没有该用户信息
throw new BizException("用户名/密码错误!");
}
//用户ID
Long userId = auth.getUserId();
SysUser sysUser = sysUserService.getById(userId);
if (sysUser == null) {
throw new BizException("用户名/密码错误!");
}
if(CS.PUB_USABLE != sysUser.getState()){ //状态不合法
throw new BizException("用户状态不可登录,请联系管理员!");
}
return new JeeUserDetails(sysUser, auth.getCredential());
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.secruity;
import com.jeequan.jeepay.mch.config.SystemYmlConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/*
* Spring Security 配置项
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:11
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启@PreAuthorize @PostAuthorize 等前置后置安全校验注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired private UserDetailsService userDetailsService;
@Autowired private JeeAuthenticationEntryPoint unauthorizedHandler;
@Autowired private SystemYmlConfig systemYmlConfig;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 使用BCrypt强哈希函数 实现PasswordEncoder
* **/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(this.userDetailsService)
.passwordEncoder(passwordEncoder());
}
/** 允许跨域请求 **/
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
if(systemYmlConfig.getAllowCors()){
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); //带上cookie信息
// config.addAllowedOrigin(CorsConfiguration.ALL); //允许跨域的域名, *表示允许任何域名使用
config.addAllowedOriginPattern(CorsConfiguration.ALL); //使用addAllowedOriginPattern 避免出现 When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.
config.addAllowedHeader(CorsConfiguration.ALL); //允许任何请求头
config.addAllowedMethod(CorsConfiguration.ALL); //允许任何方法(post、get等)
source.registerCorsConfiguration("/**", config); // CORS 配置对所有接口都有效
}
return new CorsFilter(source);
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// 由于使用的是JWT,我们这里不需要csrf
.csrf().disable()
.cors().and()
// 认证失败处理方式
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
// 添加JWT filter
httpSecurity.addFilterBefore(new JeeAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
// 禁用缓存
httpSecurity.headers().cacheControl();
}
@Override
public void configure(WebSecurity web) throws Exception {
//ignore文件 : 无需进入spring security 框架
// 1.允许对于网站静态资源的无授权访问
// 2.对于获取token的rest api要允许匿名访问
web.ignoring().antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/**/*.png",
"/**/*.jpg",
"/**/*.jpeg",
"/**/*.svg",
"/**/*.ico",
"/**/*.webp",
"/*.txt",
"/**/*.xls",
"/**/*.mp4" //支持mp4格式的文件匿名访问
)
.antMatchers(
"/api/anon/**" //匿名访问接口
);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.service;
import cn.hutool.core.util.IdUtil;
import com.jeequan.jeepay.core.cache.ITokenService;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchInfo;
import com.jeequan.jeepay.core.entity.SysUser;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.jwt.JWTPayload;
import com.jeequan.jeepay.core.jwt.JWTUtils;
import com.jeequan.jeepay.core.model.security.JeeUserDetails;
import com.jeequan.jeepay.mch.config.SystemYmlConfig;
import com.jeequan.jeepay.service.impl.MchInfoService;
import com.jeequan.jeepay.service.impl.SysRoleEntRelaService;
import com.jeequan.jeepay.service.impl.SysRoleService;
import com.jeequan.jeepay.service.impl.SysUserService;
import com.jeequan.jeepay.service.mapper.SysEntitlementMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
/**
* 认证Service
*
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Service
public class AuthService {
@Resource
private AuthenticationManager authenticationManager;
@Autowired private SysUserService sysUserService;
@Autowired private SysRoleService sysRoleService;
@Autowired private SysRoleEntRelaService sysRoleEntRelaService;
@Autowired private MchInfoService mchInfoService;
@Autowired private SysEntitlementMapper sysEntitlementMapper;
@Autowired private SystemYmlConfig systemYmlConfig;
/**
* 认证
* **/
public String auth(String username, String password){
//1. 生成spring-security usernamePassword类型对象
UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
//spring-security 自动认证过程;
// 1. 进入 JeeUserDetailsServiceImpl.loadUserByUsername 获取用户基本信息;
//2. SS根据UserDetails接口验证是否用户可用;
//3. 最后返回loadUserByUsername 封装的对象信息;
Authentication authentication = null;
try {
authentication = authenticationManager.authenticate(upToken);
} catch (AuthenticationException e) {
throw new BizException("用户名或密码有误!");
}
JeeUserDetails jeeUserDetails = (JeeUserDetails) authentication.getPrincipal();
//验证通过后 再查询用户角色和权限信息集合
SysUser sysUser = jeeUserDetails.getSysUser();
//非超级管理员 && 不包含左侧菜单 进行错误提示
if(sysUser.getIsAdmin() != CS.YES && sysEntitlementMapper.userHasLeftMenu(sysUser.getSysUserId(), CS.SYS_TYPE.MGR) <= 0){
throw new BizException("当前用户未分配任何菜单权限,请联系管理员进行分配后再登录!");
}
// 查询当前用户的商户信息
MchInfo mchInfo = mchInfoService.getById(sysUser.getBelongInfoId());
if (mchInfo != null) {
// 判断当前商户状态是否可用
if (mchInfo.getState() == CS.NO) {
throw new BizException("当前商户状态不可用!");
}
}
// 放置权限集合
jeeUserDetails.setAuthorities(getUserAuthority(sysUser));
//生成token
String cacheKey = CS.getCacheKeyToken(sysUser.getSysUserId(), IdUtil.fastUUID());
//生成iToken 并放置到缓存
ITokenService.processTokenCache(jeeUserDetails, cacheKey); //处理token 缓存信息
//将信息放置到Spring-security context中
UsernamePasswordAuthenticationToken authenticationRest = new UsernamePasswordAuthenticationToken(jeeUserDetails, null, jeeUserDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authenticationRest);
//返回JWTToken
return JWTUtils.generateToken(new JWTPayload(jeeUserDetails), systemYmlConfig.getJwtSecret());
}
/** 根据用户ID 更新缓存中的权限集合, 使得分配实时生效 **/
public void refAuthentication(List<Long> sysUserIdList){
if(sysUserIdList == null || sysUserIdList.isEmpty()){
return ;
}
Map<Long, SysUser> sysUserMap = new HashMap<>();
// 查询 sysUserId 和 state
sysUserService.list(
SysUser.gw()
.select(SysUser::getSysUserId, SysUser::getState)
.in(SysUser::getSysUserId, sysUserIdList)
).stream().forEach(item -> sysUserMap.put(item.getSysUserId(), item));
for (Long sysUserId : sysUserIdList) {
Collection<String> cacheKeyList = RedisUtil.keys(CS.getCacheKeyToken(sysUserId, "*"));
if(cacheKeyList == null || cacheKeyList.isEmpty()){
continue;
}
for (String cacheKey : cacheKeyList) {
//用户不存在 || 已禁用 需要删除Redis
if(sysUserMap.get(sysUserId) == null || sysUserMap.get(sysUserId).getState() == CS.PUB_DISABLE){
RedisUtil.del(cacheKey);
continue;
}
JeeUserDetails jwtBaseUser = RedisUtil.getObject(cacheKey, JeeUserDetails.class);
if(jwtBaseUser == null){
continue;
}
// 重新放置sysUser对象
jwtBaseUser.setSysUser(sysUserService.getById(sysUserId));
//查询放置权限数据
jwtBaseUser.setAuthorities(getUserAuthority(jwtBaseUser.getSysUser()));
//保存token 失效时间不变
RedisUtil.set(cacheKey, jwtBaseUser);
}
}
}
public List<SimpleGrantedAuthority> getUserAuthority(SysUser sysUser){
//用户拥有的角色集合 需要以ROLE_ 开头, 用户拥有的权限集合
List<String> roleList = sysRoleService.findListByUser(sysUser.getSysUserId());
List<String> entList = sysRoleEntRelaService.selectEntIdsByUserId(sysUser.getSysUserId(), sysUser.getIsAdmin(), sysUser.getSystem());
List<SimpleGrantedAuthority> grantedAuthorities = new LinkedList<>();
roleList.stream().forEach(role -> grantedAuthorities.add(new SimpleGrantedAuthority(role)));
entList.stream().forEach(ent -> grantedAuthorities.add(new SimpleGrantedAuthority(ent)));
return grantedAuthorities;
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.web;
import com.jeequan.jeepay.core.utils.ApiResBodyAdviceKit;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/**
* 自定义springMVC返回数据格式
*
* @author terrfly
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@ControllerAdvice
public class ApiResBodyAdvice implements ResponseBodyAdvice {
/** 判断哪些需要拦截 **/
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
/** 拦截返回数据处理 */
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//处理扩展字段
return ApiResBodyAdviceKit.beforeBodyWrite(body);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.web;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 数据响应拦截器
*
* @author terrfly
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Component
public class ApiResInterceptor implements HandlerInterceptor {
/** postHandler是在请求结束之后, 视图渲染之前执行的,但只有preHandle方法返回true的时候才会执行
* 如果ctrl使用了@RestController或者@ResponseBody注解 则ModelAndView = null, 因为不走视图转换器, 而是走的RequestResponseBodyMethodProcessor。
* ————————————————
*
* **/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//do
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.web;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
/**
* 上下文配置
*
* @author terrfly
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Service
public class ApplicationContextKit implements ServletContextAware,InitializingBean{
private ServletContext servletContext ;
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
/**
* afterPropertiesSet 是在什么之后执行? 启动顺序是?
* 调用PropKit(SpringBeansUtil.getBean获取方式) 会不会出现找不到bean的问题?
*
* */
@Override
public void afterPropertiesSet() throws Exception {
}
/**
* 仅在项目启动完成,并且在req请求中使用!!
* @param key
* @return
*/
public static Object getReqSession(String key){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getSession().getAttribute(key);
}
/**
* 仅在项目启动完成,并且在req请求中使用!!
* @param key
* @return
*/
public static void clearSession(String key){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
request.getSession().removeAttribute(key);
}
}
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.mch.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* webmvc配置
*
* @author terrfly
* @modify zhuxiao
* @site https://www.jeepay.vip
* @date 2021-04-27 15:50
*/
@Configuration
public class WebmvcConfig implements WebMvcConfigurer {
@Autowired
private ApiResInterceptor apiResInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(apiResInterceptor);
}
}
server:
port: 9218 #设置端口为 9218
servlet:
context-path: / #设置应用的目录. 前缀需要带/, 无需设置后缀, 示例 【 /xxx 】 or 【 / 】
spring:
mvc:
servlet:
multipart:
enabled: true #是否启用http上传处理
max-request-size: 10MB #最大请求文件的大小
max-file-size: 10MB #设置单个文件最大长度
resources:
static-locations: classpath:/static #项目静态资源路径 (可直接通过http访问)
freemarker:
template-loader-path: classpath:/templates #freemarker模板目录
template-encoding: UTF-8
suffix: .ftl
settings:
classic_compatible: true # 如果变量为null,转化为空字符串,比如做比较的时候按照空字符做比较
number_format: '#' #数字格式进行原样显示,不加格式化字符例如 100,00
datasource:
# yml填写url连接串, 无需将&符号进行转义
url: jdbc:mysql://127.0.0.1:3306/jeepay?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
username: root
password: root
druid:
# 连接池配置项
initial-size: 5 #初始化时建立物理连接的个数
min-idle: 5 #最小连接池数量
max-active: 30 #最大连接池数量
max-wait: 60000 #获取连接时最大等待时间,单位毫秒
# 检测相关
test-while-idle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
test-on-borrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
test-on-return: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
time-between-eviction-runs-millis: 60000 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
min-evictable-idle-time-millis: 300000 #连接保持空闲而不被驱逐的最小时间
validation-query: SELECT 1 FROM DUAL
# 是否缓存preparedStatement
pool-prepared-statements: false # 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
max-pool-prepared-statement-per-connection-size: 20 # 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计 通过connectProperties属性来打开mergeSql功能;慢SQL记录
filters: stat,wall
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
cache:
type: redis
redis:
host: 127.0.0.1
port: 6379
timeout: 1000
database: 2 #1库:运营平台 #2库:商户系统 #3库:支付网关
password:
#activeMQ配置
activemq:
broker-url: tcp://localhost:61616 #连接地址
#日志配置参数。
# 当存在logback-spring.xml文件时: 该配置将引进到logback配置, springboot配置不生效。
# 不存在logback-spring.xml 文件时, 使用springboot的配置, 同样可用。
logging:
level:
root: info #主日志级别
com.jeequan.jeepay: debug #该项目日志级别,当需要打印sql时请开启为debug
path: E:/logs #日志存放地址
#系统业务参数
isys:
allow-cors: true #是否允许跨域请求 [生产环境建议关闭, 若api与前端项目没有在同一个域名下时,应开启此配置或在nginx统一配置允许跨域]
jwt-secret: ARNXp4MzjOOQqxtv #生成jwt的秘钥。 要求每个系统有单独的秘钥管理机制。
# 文件系统配置项(系统内oss, 并非云oss)
oss-file:
root-path: E:/home/jeepay/files #存储根路径 ( 无需以‘/’结尾 )
public-path: ${isys.oss-file.root-path}/pubic #公共读取块 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
private-path: ${isys.oss-file.root-path}/private #私有化本地访问,不允许url方式公共读取 ( 一般配合root-path参数进行设置,需以‘/’ 开头, 无需以‘/’结尾 )
__
/ /___ ___ ____ ____ ___ __
__ / // _ \/ _ \/ __ \/ __ `/ / / /
/ /_/ // __/ __/ /_/ / /_/ / /_/ /
\____/ \___/\___/ .___/\__,_/\__, /
/_/ /____/
:: Jeepay :: (v1.0.0.RELEASE)
适合互联网企业使用的开源支付系统 : https://www.jeepay.vip
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" debug="false">
<!-- 日志存放路径, 读取application.yml 需要使用springProperty获取 -->
<springProperty scope="context" name="currentLoggerFilePath" source="logging.path"/>
<!-- 主日志级别配置 -->
<springProperty scope="context" name="currentRootLevel" source="logging.level.root"/>
<!-- 项目配置, 如修改包名,请搜索并全部替换掉 -->
<springProperty scope="context" name="currentProjectLevel" source="logging.level.com.jeequan.jeepay"/>
<!-- 日志文件名称 logback属性 -->
<property name="currentLoggerFileName" value="mch" />
<!-- 日志格式, 参考:https://logback.qos.ch/manual/layouts.html -->
<property name="currentLoggerPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%logger{15}] - %msg%n" />
<!-- appender: 控制台日志 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="UTF-8" >
<pattern>${currentLoggerPattern}</pattern>
</encoder>
</appender>
<!-- appender:主日志文件 -->
<appender name="ALL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件路径及文件名 -->
<file>${currentLoggerFilePath}/${currentLoggerFileName}.all.log</file>
<!-- 内容编码及格式 -->
<encoder charset="UTF-8" ><pattern>${currentLoggerPattern}</pattern></encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${currentLoggerFilePath}/${currentLoggerFileName}.all.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>10</maxHistory> <!--日志文件保留天数-->
</rollingPolicy>
</appender>
<!-- appender:错误信息日志文件 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志文件路径及文件名 -->
<file>${currentLoggerFilePath}/${currentLoggerFileName}.error.log</file>
<!-- 内容编码及格式 -->
<encoder charset="UTF-8" ><pattern>${currentLoggerPattern}</pattern></encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${currentLoggerFilePath}/${currentLoggerFileName}.error.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>20</maxHistory> <!--日志文件保留天数-->
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 主日志级别配置 -->
<root level="${currentRootLevel}">
<appender-ref ref="STDOUT" />
<appender-ref ref="ALL_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
<!-- 项目日志级别配置 -->
<logger name="com.jeequan.jeepay" level="${currentProjectLevel}"/>
</configuration>
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion> <!-- POM模型版本 -->
<groupId>org.xxpay</groupId> <groupId>com.jeequan</groupId> <!-- 组织名, 类似于包名 -->
<artifactId>xxpay4spring-boot</artifactId> <artifactId>jeepay-payment</artifactId> <!-- 项目名称 -->
<version>1.0.0</version> <packaging>jar</packaging> <!-- 项目的最终打包类型/发布形式, 可选[jar, war, pom, maven-plugin]等 -->
<packaging>jar</packaging> <version>${isys.version}</version> <!-- 项目当前版本号 -->
<name>xxpay4spring-boot</name> <description>Jeepay计全支付系统 [统一支付网关]</description> <!-- 项目描述 -->
<description>xxpay4spring-boot</description> <url>https://www.jeequan.com</url>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>com.jeequan</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>jeepay</artifactId>
<version>1.5.6.RELEASE</version> <version>1.0.0</version>
</parent> </parent>
<!-- 项目依赖声明 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<springboot.version>1.5.6.RELEASE</springboot.version>
<springboot.dubbo.version>1.0.0</springboot.dubbo.version>
</properties>
<dependencies> <dependencies>
<!-- 依赖[ service ]包, 会自动传递依赖[ core ]包。 -->
<dependency> <dependency>
<groupId>org.xxpay</groupId> <groupId>com.jeequan</groupId>
<artifactId>xxpay-dal</artifactId> <artifactId>jeepay-service</artifactId>
<version>1.0.0</version> <version>${isys.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency> </dependency>
<!-- 依赖 sping-boot-web -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion> <!-- 删除spring boot默认json映射器: Jackson, 引入fastJSON -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- freemarker -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId> <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency> </dependency>
<!-- hibernate.validator插件 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.hibernate.validator</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>hibernate-validator</artifactId>
</dependency> </dependency>
<!-- 添加redis支持 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>
<scope>test</scope>
</dependency> </dependency>
<!-- 添加对activeMQ的支持 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-starter-activemq</artifactId>
</dependency> </dependency>
<!--wx_pay https://github.com/wechat-group/WxJava -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>spring-boot-starter-activemq</artifactId> <artifactId>weixin-java-pay</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.activemq</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>activemq-pool</artifactId> <artifactId>weixin-java-mp</artifactId>
</dependency> </dependency>
<!-- 生成二维码工具包 zxing -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>com.google.zxing</groupId>
<artifactId>spring-boot-starter-amqp</artifactId> <artifactId>core</artifactId>
</dependency> </dependency>
<!--wx_pay-->
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.google.zxing</groupId>
<artifactId>weixin-java-pay</artifactId> <artifactId>javase</artifactId>
<version>2.8.0</version>
</dependency> </dependency>
<!--ali_pay-->
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
<dependency> <dependency>
<groupId>com.alipay</groupId> <groupId>com.alipay.sdk</groupId>
<artifactId>sdk</artifactId> <artifactId>alipay-sdk-java</artifactId>
<version>1.5</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/webapp/WEB-INF/lib/alipay-sdk-java20170818173712.jar</systemPath>
</dependency> </dependency>
</dependencies> </dependencies>
<!-- 作为可执行jar -->
<build> <build>
<resources> <finalName>${project.artifactId}</finalName>
<resource>
<directory>src/main/webapp/WEB-INF/lib/</directory>
<targetPath>BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<targetPath>BOOT-INF/classes/</targetPath>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<finalName>${project.name}</finalName>
</configuration>
</plugin> </plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
</plugins> </plugins>
</build> </build>
</project>
\ No newline at end of file </project>
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.bootstrap;
import cn.hutool.core.date.DatePattern;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Date;
/*
* 项目初始化操作
* 比如初始化配置文件, 读取基础数据, 资源初始化等。 避免在Main函数中写业务代码。
* CommandLineRunner / ApplicationRunner都可以达到要求, 只是调用参数有所不同。
*
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/8 17:17
*/
@Component
public class InitRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
//初始化处理fastjson格式
SerializeConfig serializeConfig = SerializeConfig.getGlobalInstance();
serializeConfig.put(Date.class, new SimpleDateFormatSerializer(DatePattern.NORM_DATETIME_PATTERN));
//解决json 序列化时候的 $ref:问题
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment