Commit 1c649d28 by 袁伟铭

添加婚姻统计接口

parent 2600160c
package com.zq.common.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* 存放系统所有用户的基本信息(Pfuser)实体类
*
* @author makejava
* @since 2021-06-23 17:55:12
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@TableName(value = "pfuser")
public class Pfuser {
/**
* 用户ID ( 由序列号生成,前两位为系统编号,后面7位为序列号)
*/
@TableId
@ApiModelProperty(" 用户ID ( 由序列号生成,前两位为系统编号,后面7位为序列号)")
private Long userid;
/**
* 状态 ( 0为正常1为冻结2为删除 )
*/
@ApiModelProperty(" 状态 ( 0为正常1为冻结2为删除 )")
private Long state;
/**
* 用户类型 ( 0为内网用户1为外网用户 )
*/
@ApiModelProperty(" 用户类型 ( 0为内网用户1为外网用户 )")
private Long type;
/**
* 用户姓名
*/
@ApiModelProperty(" 用户姓名 ")
private String username;
/**
* 密码 ( Md5之后保存在数据库中 )
*/
@ApiModelProperty(" 密码 ( Md5之后保存在数据库中 )")
private String password;
/**
* 是否为超级管理员 ( 0为普通用户1为超级管理员 对于超级管理员将不做任何权限验证,可以看到所有的菜单)
*/
@ApiModelProperty(" 是否为超级管理员 ( 0为普通用户1为超级管理员 对于超级管理员将不做任何权限验证,可以看到所有的菜单)")
private Long adminuser;
/**
* 用户姓名的中文简拼 ( 用于快速查找 )
*/
@ApiModelProperty(" 用户姓名的中文简拼 ( 用于快速查找 )")
private String simplespell;
/**
* 办公电话 ( 用户的办公电话 )
*/
@ApiModelProperty(" 办公电话 ( 用户的办公电话 )")
private String officephone;
/**
* 数据过滤类型 ( 当一个用户属于多个部门时,此字段有效,0表示只查看当前登录的部门的数据,1表示查看所属的多个部门的数据,在个人配置中设置 )
*/
@ApiModelProperty(" 数据过滤类型 ( 当一个用户属于多个部门时,此字段有效,0表示只查看当前登录的部门的数据,1表示查看所属的多个部门的数据,在个人配置中设置 )")
private Long deptdatatype;
/**
* 手机号码 ( 用户的手机号码 )
*/
@ApiModelProperty(" 手机号码 ( 用户的手机号码 )")
private String phone;
/**
* 登录名 ( 唯一约束 )
*/
@ApiModelProperty(" 登录名 ( 唯一约束 )")
private String loginname;
/**
* 原系统邮件地址 ( 当用户是从其他系统(如旧的平台)中对接过来时,保存原系统用户的邮件地址 )
*/
@ApiModelProperty(" 原系统邮件地址 ( 当用户是从其他系统(如旧的平台)中对接过来时,保存原系统用户的邮件地址 )")
private String sourcemail;
/**
* 证书ID ( 一个用户可以有多个证书,多个证书的id之间用空格分开 )
*/
@ApiModelProperty(" 证书ID ( 一个用户可以有多个证书,多个证书的id之间用空格分开 )")
private String certid;
/**
* 用户姓名的中文拼音 ( 用于快速查找 )
*/
@ApiModelProperty(" 用户姓名的中文拼音 ( 用于快速查找 )")
private String spell;
/**
* 登录方式 ( 0 如果绑定了证书则用证书登录,否则用用户名密码登录1 只允许用证书登录2 只允许用用户名密码登录3 两种登录方式可同时使用 )
*/
@ApiModelProperty(" 登录方式 ( 0 如果绑定了证书则用证书登录,否则用用户名密码登录1 只允许用证书登录2 只允许用用户名密码登录3 两种登录方式可同时使用 )")
private Long logintype;
/**
* 性别 ( 0为男1为女 )
*/
@ApiModelProperty(" 性别 ( 0为男1为女 )")
private Long sex;
/**
* 证书类型 ( 一个系统可以同时支持多个类型的证书,这个字段保存此用户使用的证书类型的ID,如果gdca,证书类型在WEB-INF/system.xml中配置 )
*/
@ApiModelProperty(" 证书类型 ( 一个系统可以同时支持多个类型的证书,这个字段保存此用户使用的证书类型的ID,如果gdca,证书类型在WEB-INF/system.xml中配置 )")
private String certtype;
/**
* 生日
*/
@ApiModelProperty(" 生日 ")
private Date birthday;
/**
* 工作时间
*/
@ApiModelProperty(" 工作时间 ")
private Date workday;
/**
* 原系统ID ( 当用户是从其他系统(如旧的平台)中对接过来时,保存原系统的ID )
*/
@ApiModelProperty(" 原系统ID ( 当用户是从其他系统(如旧的平台)中对接过来时,保存原系统的ID )")
private String sourceid;
/**
* 证件类型 ( 0为身份证1为军官证 )
*/
@ApiModelProperty(" 证件类型 ( 0为身份证1为军官证 )")
private Long idcardtype;
/**
* 证件号码 ( 身份证号码或者军官证号码 )
*/
@ApiModelProperty(" 证件号码 ( 身份证号码或者军官证号码 )")
private String idcardno;
/**
* levelid
*/
private Long levelid;
/**
* workno
*/
private String workno;
/**
* duty
*/
private String duty;
/**
* uuid
*/
private String uuid;
/**
* updatetime
*/
private Date updatetime;
/**
* test
*/
private Long test;
/**
* createtime
*/
private Date createtime;
}
......@@ -54,7 +54,7 @@ public class SystemArea {
private String parentId;
public String subAreaCode() {
String sbId = "";
String sbId = "45";
if (type == 0 || StringUtils.isBlank(code)) {
return sbId;
}
......
......@@ -13,6 +13,9 @@ api.name: API-SERVER
portal.port: 9700
portal.name: PORTAL-SERVER
user.port: 9800
user.name: USER-SERVER
gateway.port: 9888
gateway.name: GATEWAY-SERVER
......
......@@ -13,6 +13,9 @@ api.name: API-SERVER
portal.port: 9700
portal.name: PORTAL-SERVER
user.port: 9800
user.name: USER-SERVER
gateway.port: 9888
gateway.name: GATEWAY-SERVER
......
......@@ -3,6 +3,8 @@ package com.zq.portal;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
......@@ -16,18 +18,24 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
*/
@Configuration
@EnableSwagger2
public class Swagger {
public class Swagger implements WebMvcConfigurer {
@Value("${spring.cloud.config.profile}")
private String profile;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("后台管理")
.groupName("admin")
.enable(!"product".equals(profile)) //生产环境关闭
.select()
.apis(RequestHandlerSelectors.basePackage("com.zq.cms.controller"))
.apis(RequestHandlerSelectors.basePackage("com.zq.portal.controller.admin"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo());
......@@ -43,10 +51,10 @@ public class Swagger {
@Bean
public Docket app() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("App项目")
.groupName("App")
.enable(!"product".equals(profile)) //生产环境关闭
.select()
.apis(RequestHandlerSelectors.basePackage("com.zq.cms.controller"))
.apis(RequestHandlerSelectors.basePackage("com.zq.portal.controller.app"))
.paths(PathSelectors.any())
.build()
.apiInfo(appInfo());
......
......@@ -6,5 +6,4 @@ public class DBName {
public final static String GXDB = "gxdb";
public final static String GXHY = "gxhy";
public final static String GXSHZZ = "gxshzz";
}
......@@ -77,7 +77,7 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
Set<String> apiSet = new HashSet<>();
//不使用注解的时候在这添加url放行
apiSet.add("/portal/app/**");
// apiSet.add("/static/map/**");
apiSet.add("/**");
anonymousUrls.put("API", apiSet);
httpSecurity
......
package com.zq.portal.controller.admin;
import com.zq.common.vo.ResultVo;
import com.zq.portal.service.StatsService;
import com.zq.portal.vo.StatsReqVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "婚姻相关接口")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/portal/admin/stats")
public class HyAdminStatsController {
public final StatsService statsService;
@ApiOperation("获取结婚离婚人数")
@PostMapping(value = "/getTotalMarryDivorce")
public ResultVo getTotalMarryDivorce(@RequestBody StatsReqVo vo) {
return ResultVo.success(statsService.getTotalMarryDivorce(vo));
}
@ApiOperation("获取地区结婚离婚人数列表")
@PostMapping(value = "/getAreaMarryDivorceList")
public ResultVo getAreaMarryDivorceList(@RequestBody StatsReqVo vo) {
return ResultVo.success(statsService.getAreaMarryDivorceList(vo));
}
@ApiOperation("获取地区结婚离婚人数列表")
@PostMapping(value = "/getDivorceCoolingLine")
public ResultVo getDivorceCoolingLine(@RequestBody StatsReqVo vo) {
return ResultVo.success(statsService.getDivorceCoolingLine(vo));
}
}
......@@ -10,6 +10,7 @@ import com.zq.portal.service.PeopleService;
import com.zq.portal.service.StatsService;
import com.zq.portal.vo.AreaVo;
import com.zq.portal.vo.IdVo;
import com.zq.portal.vo.StatsReqVo;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
......@@ -181,13 +182,4 @@ public class StatsAdminController {
return statsFegin.checkIsTrue(vo);
}
/********************************************************/
@ApiOperation("获取地图统计数据")
@PostMapping(value = "/getMapStatsData")
public ResultVo getMapStatsData(@RequestBody AreaVo vo) {
return ResultVo.success(statsService.getMapStatsData(vo));
}
}
package com.zq.portal.controller.app;
import com.zq.common.vo.ResultVo;
import com.zq.portal.service.StatsService;
import com.zq.portal.vo.StatsReqVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "统计相关接口")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/portal/app/stats")
public class CjStatsController {
public final StatsService statsService;
@ApiOperation("残疾人两项补贴")
@PostMapping(value = "/cjTwoSubsidies")
public ResultVo cjTwoSubsidies(@RequestBody StatsReqVo vo) {
return ResultVo.success(statsService.cjTwoSubsidies(vo));
}
}
package com.zq.portal.controller.app;
import com.zq.common.vo.ResultVo;
import com.zq.portal.service.StatsService;
import com.zq.portal.vo.StatsReqVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "婚姻相关接口")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/portal/app/stats")
public class HyStatsController {
public final StatsService statsService;
@ApiOperation("获取结婚离婚人数")
@PostMapping(value = "/getTotalMarryDivorce")
public ResultVo getTotalMarryDivorce(@RequestBody StatsReqVo vo) {
return ResultVo.success(statsService.getTotalMarryDivorce(vo));
}
@ApiOperation("获取地区结婚离婚人数列表")
@PostMapping(value = "/getAreaMarryDivorceList")
public ResultVo getAreaMarryDivorceList(@RequestBody StatsReqVo vo) {
return ResultVo.success(statsService.getAreaMarryDivorceList(vo));
}
}
package com.zq.portal.controller.app;
import com.zq.common.vo.ResultVo;
import com.zq.portal.manager.CacheKeys;
import com.zq.portal.manager.PortalCacheManager;
import com.zq.portal.service.StatsService;
import com.zq.portal.vo.AreaVo;
import com.zq.portal.vo.StatsReqVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
......@@ -18,10 +20,16 @@ import org.springframework.web.bind.annotation.RestController;
public class StatsController {
public final StatsService statsService;
public final PortalCacheManager portalCacheManager;
@ApiOperation("获取地图统计数据")
@PostMapping(value = "/getMapStatsData")
public ResultVo getMapStatsData(@RequestBody AreaVo vo) {
public ResultVo getMapStatsData(@RequestBody StatsReqVo vo) {
Object obj = portalCacheManager.getObj(CacheKeys.getMapDataKey(vo.getAreaCode()));
if (obj != null) {
return ResultVo.success(obj);
}
return ResultVo.success(statsService.getMapStatsData(vo));
}
......
package com.zq.portal.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zq.common.entity.SystemArea;
import com.zq.common.entity.SystemYear;
import org.apache.ibatis.annotations.Mapper;
......@@ -11,7 +12,7 @@ import java.util.Map;
@Mapper
@Repository
public interface AreaDao {
public interface AreaDao extends BaseMapper<SystemArea> {
List<SystemArea> getAreaList(SystemArea area);
......
......@@ -2,7 +2,7 @@ package com.zq.portal.dao;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.zq.portal.config.DBName;
import com.zq.portal.vo.YearStatsVo;
import com.zq.portal.vo.StatsVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
......@@ -12,6 +12,6 @@ import java.util.List;
@Repository
public interface BzStatsDao {
List<YearStatsVo> getDeathsPerYear(@Param("areaCode") String areaCode);
List<StatsVo> getDeathsPerYear(@Param("areaCode") String areaCode);
}
package com.zq.portal.dao;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.zq.portal.config.DBName;
import org.springframework.stereotype.Repository;
@DS(DBName.GXCJ)
@Repository
public interface CjStatsDao {
}
......@@ -2,7 +2,7 @@ package com.zq.portal.dao;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.zq.portal.config.DBName;
import com.zq.portal.vo.YearStatsVo;
import com.zq.portal.vo.StatsVo;
import org.springframework.stereotype.Repository;
import java.util.List;
......@@ -11,6 +11,6 @@ import java.util.List;
@Repository
public interface DbStatsDao {
List<YearStatsVo> getMarryPerYear();
List<StatsVo> getMarryPerYear();
}
......@@ -2,7 +2,9 @@ package com.zq.portal.dao;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.zq.portal.config.DBName;
import com.zq.portal.vo.YearStatsVo;
import com.zq.portal.vo.StatsReqVo;
import com.zq.portal.vo.StatsVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
......@@ -11,6 +13,20 @@ import java.util.List;
@Repository
public interface HyStatsDao {
List<YearStatsVo> getMarryPerYear(String areaCode);
/**
* 获取结婚离婚人数
*
* @param vo
* @return
*/
List<StatsVo> getTotalMarryDivorce(StatsReqVo vo);
// 获取结婚人数
StatsVo getMarryNum(@Param("areaCode") String areaCode, @Param("year") String year);
// 获取离婚人数
StatsVo getDivorceNum(@Param("subAreaCode") String subAreaCode, @Param("year") String year);
// 获取每月冷静期数据
List<StatsVo> getMonthDivorceCoolingData(StatsReqVo vo);
}
......@@ -2,7 +2,7 @@ package com.zq.portal.dao;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.zq.portal.config.DBName;
import com.zq.portal.vo.YearStatsVo;
import com.zq.portal.vo.StatsVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
......@@ -18,6 +18,6 @@ public interface ShzzStatsDao {
* @param areaCode
* @return
*/
List<YearStatsVo> getSoorganPerYear(@Param("areaCode") String areaCode);
List<StatsVo> getSoorganPerYear(@Param("areaCode") String areaCode);
}
package com.zq.portal.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zq.common.entity.SystemArea;
import com.zq.common.utils.AssertUtils;
import com.zq.common.utils.StringUtils;
import com.zq.portal.dao.AreaDao;
import com.zq.portal.dao.BzStatsDao;
import com.zq.portal.dao.HyStatsDao;
import com.zq.portal.dao.ShzzStatsDao;
import com.zq.portal.manager.CacheKeys;
import com.zq.portal.manager.PortalCacheManager;
import com.zq.portal.vo.AreaVo;
import com.zq.portal.vo.YearStatsVo;
import com.zq.portal.vo.StatsReqVo;
import com.zq.portal.vo.StatsVo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
......@@ -28,15 +30,10 @@ public class StatsService {
private final AreaDao areaDao;
private final PortalCacheManager portalCacheManager;
public Object getMapStatsData(AreaVo vo) {
// Object obj = portalCacheManager.getObj(CacheKeys.getMapDataKey(vo.getPId()));
// if (obj != null) {
// return obj;
// }
public Object getMapStatsData(StatsReqVo vo) {
List<Map<String, Object>> returnData = new ArrayList<>();
//获取子区域
List<SystemArea> kid = areaDao.findKid(vo.getPId());
List<SystemArea> kid = areaDao.findKid(vo.getAreaCode());
AssertUtils.isTrue(kid != null && kid.size() > 0, "该地区没有数据");
for (SystemArea systemArea : kid) {
......@@ -44,13 +41,13 @@ public class StatsService {
Map<String, Object> areaData = new HashMap<>();
String areaCode = systemArea.subAreaCode();
// 每年死亡人数
List<YearStatsVo> deathsPerYear = bzStatsDao.getDeathsPerYear(areaCode);
List<StatsVo> deathsPerYear = bzStatsDao.getDeathsPerYear(areaCode);
// 每年结婚人数
List<YearStatsVo> marryPerYear = hyStatsDao.getMarryPerYear(areaCode);
// List<YearStatsVo> marryPerYear = hyStatsDao.getMarryPerYear(areaCode);
// 每年社会组织数量
List<YearStatsVo> soorganPerYear = shzzStatsDao.getSoorganPerYear(areaCode);
List<StatsVo> soorganPerYear = shzzStatsDao.getSoorganPerYear(areaCode);
areaData.put("deathsPerYear", deathsPerYear);
areaData.put("marryPerYear", marryPerYear);
// areaData.put("marryPerYear", marryPerYear);
areaData.put("soorganPerYear", soorganPerYear);
areaData.put("areaName", systemArea.getName());
areaData.put("areaCode", systemArea.getCode());
......@@ -58,10 +55,73 @@ public class StatsService {
}
if (returnData.size() > 0) {
portalCacheManager.setObj(CacheKeys.getMapDataKey(vo.getPId()), returnData);
portalCacheManager.setObj(CacheKeys.getMapDataKey(vo.getAreaCode()), returnData);
}
return returnData;
}
/**
* 获取总离婚结婚人数
*
* @param vo
* @return
*/
public Object getTotalMarryDivorce(StatsReqVo vo) {
if (StringUtils.isBlank(vo.getAreaCode())) {
vo.setAreaCode("450000000000");
}
SystemArea area = areaDao.getAreaByCode(vo.getAreaCode());
vo.setAreaCode(area.subAreaCode());
List<StatsVo> totalMarryDivorce = hyStatsDao.getTotalMarryDivorce(vo);
return totalMarryDivorce;
}
/**
* 获取区域下的结婚离婚数据
*
* @param vo
* @return
*/
public Object getAreaMarryDivorceList(StatsReqVo vo) {
if (StringUtils.isBlank(vo.getAreaCode())) {
vo.setAreaCode("450000000000");
}
SystemArea area = areaDao.getAreaByCode(vo.getAreaCode());
vo.setAreaCode(area.subAreaCode());
List<Map<String, Object>> returnData = new ArrayList<>();
List<SystemArea> systemAreaList = areaDao.selectList(Wrappers.lambdaQuery(SystemArea.builder().parentId(area.getCode()).build()));
for (SystemArea systemArea : systemAreaList) {
Map<String, Object> areaData = new HashMap<>();
List<StatsVo> totalMarryDivorce = hyStatsDao.getTotalMarryDivorce(StatsReqVo.builder().areaCode(systemArea.subAreaCode()).build());
areaData.put("data", totalMarryDivorce);
areaData.put("areaName", systemArea.getName());
areaData.put("areaCode", systemArea.getCode());
returnData.add(areaData);
}
return returnData;
}
public Object cjTwoSubsidies(StatsReqVo vo) {
if (StringUtils.isBlank(vo.getAreaCode())) {
vo.setAreaCode("450000000000");
}
SystemArea systemArea = areaDao.selectById(vo.getAreaCode());
return null;
}
/**
* 获取冷静期和真正离婚的折线图数据
*
* @param vo
* @return
*/
public Object getDivorceCoolingLine(StatsReqVo vo) {
// 获取冷静期
List<StatsVo> statsVoList = hyStatsDao.getMonthDivorceCoolingData(vo);
return null;
}
}
......@@ -24,7 +24,7 @@ public class AreaVo {
/**
* 区域ID
*/
private String id;
private String areaId;
/**
* 年份
*/
......
package com.zq.portal.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StatsReqVo {
/**
* 区域ID
*/
private String areaCode;
/**
* 年份
*/
private Integer year;
/**
* 年份
*/
private Integer month;
/**
* 开始时间
*/
private String startTime;
/**
* 结算时间
*/
private String endTime;
}
......@@ -3,10 +3,14 @@ package com.zq.portal.vo;
import lombok.Data;
@Data
public class YearStatsVo {
public class StatsVo {
private String year;
private Integer num;
private String type;
private String month;
}
......@@ -28,33 +28,13 @@ spring:
dynamic: # mybatis plus多数据源插件
primary: master #设置默认的数据源或者数据源组,默认值即为master
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
druid:
# 初始连接数
initial-size: 5
# 最小连接数
min-idle: 10
# 最大连接数
max-active: 20
# 获取连接超时时间
max-wait: 5000
# 连接有效性检测时间
time-between-eviction-runs-millis: 60000
# 连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
# 连接在池中最大生存的时间
max-evictable-idle-time-millis: 900000
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 检测连接是否有效
validation-query: select 1
datasource:
master:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.0.193:3306/mz_big_data?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: rooT123!321
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${jdbc.url}
username: ${jdbc.username}
password: ${jdbc.password}
driver-class-name: ${jdbc.driver-class-name}
gxbz:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.0.193:3306/gx-bz?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
......@@ -79,54 +59,33 @@ spring:
username: root
password: rooT123!321
driver-class-name: com.mysql.cj.jdbc.Driver
gxshzz:
shzz:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.0.193:3306/gx-shzz?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
url: jdbc:mysql://192.168.0.193:3306/shzz?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: rooT123!321
driver-class-name: com.mysql.cj.jdbc.Driver
# druid:
# db-type: com.alibaba.druid.pool.DruidDataSource
# driverClassName: ${jdbc.driver-class-name}
# username: ${jdbc.username}
# password: ${jdbc.password}
# url: ${jdbc.url}
# # 初始连接数
# initial-size: 5
# # 最小连接数
# min-idle: 10
# # 最大连接数
# max-active: 20
# # 获取连接超时时间
# max-wait: 5000
# # 连接有效性检测时间
# time-between-eviction-runs-millis: 60000
# # 连接在池中最小生存的时间
# min-evictable-idle-time-millis: 300000
# # 连接在池中最大生存的时间
# max-evictable-idle-time-millis: 900000
# test-while-idle: true
# test-on-borrow: false
# test-on-return: false
# # 检测连接是否有效
# validation-query: select 1
# # 配置监控统计
# webStatFilter:
# enabled: true
# stat-view-servlet:
# enabled: true
# url-pattern: /druid/*
# reset-enable: false
# filter:
# stat:
# enabled: true
# # 记录慢SQL
# log-slow-sql: true
# slow-sql-millis: 1000
# merge-sql: true
# wall:
# config:
# multi-statement-allow: true
druid:
# 初始连接数
initial-size: 5
# 最小连接数
min-idle: 10
# 最大连接数
max-active: 20
# 获取连接超时时间
max-wait: 5000
# 连接有效性检测时间
time-between-eviction-runs-millis: 60000
# 连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
# 连接在池中最大生存的时间
max-evictable-idle-time-millis: 900000
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 检测连接是否有效
validation-query: select 1
# mybatis plus 配置
mybatis-plus:
global-config:
......
......@@ -58,7 +58,7 @@
</select>
<select id="getAreaByCode" parameterType="java.lang.String" resultType="com.zq.common.entity.SystemArea">
SELECT id as id, type ,parent_id as parentId,name FROM system_area a where a.id=#{value}
SELECT id as id, code, type ,parent_id as parentId,name FROM system_area a where a.id=#{value}
</select>
<select id="getAreaByPartmentId" parameterType="string" resultType="string">
......
......@@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zq.portal.dao.BzStatsDao">
<select id="getDeathsPerYear" resultType="com.zq.portal.vo.YearStatsVo">
<select id="getDeathsPerYear" resultType="com.zq.portal.vo.StatsVo">
SELECT
COUNT(1) 'num', LEFT(i.DEATH_DATE,4) 'year'
FROM
......
......@@ -2,16 +2,93 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zq.portal.dao.HyStatsDao">
<select id="getMarryPerYear" resultType="com.zq.portal.vo.YearStatsVo">
<select id="getMarryPerYear" resultType="com.zq.portal.vo.StatsVo">
SELECT COUNT(1) 'num', DATE_FORMAT(m.AIAX0048,"%Y") 'year'
FROM mrcase m
WHERE (m.AIAP0013 LIKE CONCAT(#{areaCode}, '%') OR m.AIAP0014 LIKE CONCAT(#{areaCode}, '%'))
GROUP BY DATE_FORMAT(m.AIAX0048, "%Y")
ORDER BY DATE_FORMAT(m.AIAX0048, "%Y") DESC LIMIT 3
</select>
<select id="getTotalMarryDivorce" resultType="com.zq.portal.vo.StatsVo">
SELECT
COUNT(1) 'num', DATE_FORMAT(m.AIAX0048,"%Y") 'year'
COUNT( 1 ) 'num',
m.AIAX0001 'type'
FROM
mrcase m
WHERE (m.AIAP0013 LIKE CONCAT(#{areaCode},'%') OR m.AIAP0014 LIKE CONCAT(#{areaCode},'%'))
mrcase m
WHERE
m.AIAX0072 = '1'
AND m.BIAX0075 = '1'
<if test="startTime != null and startTime != ''">
AND AIAX0048 >= #{startTime}
</if>
<if test="endTime != null and endTime != ''">
AND AIAX0048 &lt;= #{endTime}
</if>
<if test="areaCode != null and areaCode != ''">
AND AIAP0013 LIKE CONCAT(#{areaCode},'%')
</if>
GROUP BY
DATE_FORMAT(m.AIAX0048,"%Y")
ORDER BY DATE_FORMAT(m.AIAX0048,"%Y") DESC
LIMIT 3
m.AIAX0001
</select>
<select id="getMarryNum" resultType="com.zq.portal.vo.StatsVo">
SELECT
COUNT(1) 'num', AIAX0001 'type'
FROM
mrcase
WHERE AIAX0001 = 'IA' AND AIAX0072 = 1
<if test="year != null">
AND AIAX0048 >= #{year}
</if>
<if test="areaCode != null and areaCode != ''">
AND (AIAP0013 LIKE CONCAT(#{areaCode},'%') OR AIAP0014 LIKE CONCAT(#{areaCode},'%'))
</if>
</select>
<select id="getDivorceNum" resultType="com.zq.portal.vo.StatsVo">
SELECT
COUNT(1) 'num', AIAX0001 'type'
FROM
mrcase
WHERE AIAX0001 = 'IA' AND AIAX0072 = 1
<if test="year != null">
AND AIAX0048 >= #{year}
</if>
<if test="areaCode != null and areaCode != ''">
AND (AIAP0013 LIKE CONCAT(#{areaCode},'%') OR AIAP0014 LIKE CONCAT(#{areaCode},'%'))
</if>
</select>
<select id="getMonthDivorceCoolingData" resultType="com.zq.portal.vo.StatsVo">
SELECT
LEFT(m.AIAX0048,10),
COUNT(1) 'num'
FROM
mrcheck m
LEFT JOIN mrcheckappend ma ON m.BIAX0069 = ma.BIAX0069
WHERE
m.AIAX0001 = 'IB'
AND m.AIAX0072 = '1'
AND m.BIAX0015 = '6'
AND ma.COLEENDTIME &lt; CURDATE()
GROUP BY LEFT(m.AIAX0048,10)
</select>
<select id="getMonthDivorceData" resultType="com.zq.portal.vo.StatsVo">
SELECT
LEFT(m.AIAX0048,10),
COUNT(1) 'num'
FROM
mrcheck m
LEFT JOIN mrcheckappend ma ON m.BIAX0069 = ma.BIAX0069
WHERE
m.AIAX0001 = 'IB'
AND m.AIAX0072 = '1'
AND m.BIAX0015 = '6'
AND ma.COLEENDTIME > CURDATE()
GROUP BY LEFT(m.AIAX0048,10)
</select>
</mapper>
......@@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zq.portal.dao.ShzzStatsDao">
<select id="getSoorganPerYear" resultType="com.zq.portal.vo.YearStatsVo">
<select id="getSoorganPerYear" resultType="com.zq.portal.vo.StatsVo">
SELECT
COUNT(1) 'num', DATE_FORMAT(s.issueTime,"%Y") 'year'
FROM
......
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.zq.user.config;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Zheng Jie
*/
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
//当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应
response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
}
}
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.zq.user.config;
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;
/**
* @author Zheng Jie
*/
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
// 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException == null ? "Unauthorized" : authException.getMessage());
}
}
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.zq.user.config;
import com.zq.common.annotation.AnonymousAccess;
import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties;
import com.zq.common.utils.RequestMethodEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.*;
/**
* @author Zheng Jie
*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
private final TokenProvider tokenProvider;
private final JwtAuthenticationEntryPoint authenticationErrorHandler;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final ApplicationContext applicationContext;
private final SecurityProperties properties;
private final RedisUtils redisUtils;
@Bean
public GrantedAuthorityDefaults grantedAuthorityDefaults() {
// 去除 ROLE_ 前缀
return new GrantedAuthorityDefaults("");
}
@Bean
public PasswordEncoder passwordEncoder() {
// 密码加密方式
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// 搜寻匿名标记 url: @AnonymousAccess
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
// 获取匿名标记
Map<String, Set<String>> anonymousUrls = getAnonymousUrl(handlerMethodMap);
Set<String> apiSet = new HashSet<>();
//不使用注解的时候在这添加url放行
apiSet.add("/user/app/**");
anonymousUrls.put("API", apiSet);
httpSecurity
// 禁用 CSRF
.csrf().disable()
// .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
// 授权异常
.exceptionHandling()
.authenticationEntryPoint(authenticationErrorHandler)
.accessDeniedHandler(jwtAccessDeniedHandler)
// 防止iframe 造成跨域
.and()
.headers()
.frameOptions()
.disable()
// 不创建会话
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// 静态资源等等
.antMatchers(
HttpMethod.GET,
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/webSocket/**"
).permitAll()
// swagger 文档
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/webjars/**").permitAll()
.antMatchers("/*/api-docs").permitAll()
// 文件
.antMatchers("/avatar/**").permitAll()
.antMatchers("/file/**").permitAll()
// 阿里巴巴 druid
.antMatchers("/druid/**").permitAll()
// 放行OPTIONS请求
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型
// GET
.antMatchers(HttpMethod.GET, anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()
// POST
.antMatchers(HttpMethod.POST, anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()
// PUT
.antMatchers(HttpMethod.PUT, anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()
// PATCH
.antMatchers(HttpMethod.PATCH, anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()
// DELETE
.antMatchers(HttpMethod.DELETE, anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()
// 所有类型的接口都放行
.antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()
// API接口放行
.antMatchers(anonymousUrls.get("API").toArray(new String[0])).permitAll()
// 所有请求都需要认证
.anyRequest().authenticated()
.and().apply(securityConfigurerAdapter());
}
private TokenConfigurer securityConfigurerAdapter() {
return new TokenConfigurer(tokenProvider, properties, redisUtils);
}
private Map<String, Set<String>> getAnonymousUrl(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) {
Map<String, Set<String>> anonymousUrls = new HashMap<>(6);
Set<String> get = new HashSet<>();
Set<String> post = new HashSet<>();
Set<String> put = new HashSet<>();
Set<String> patch = new HashSet<>();
Set<String> delete = new HashSet<>();
Set<String> all = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
if (null != anonymousAccess) {
List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
switch (Objects.requireNonNull(request)) {
case GET:
get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case POST:
post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case PUT:
put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case PATCH:
patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
case DELETE:
delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
default:
all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
break;
}
}
}
anonymousUrls.put(RequestMethodEnum.GET.getType(), get);
anonymousUrls.put(RequestMethodEnum.POST.getType(), post);
anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);
anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);
anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);
anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);
return anonymousUrls;
}
}
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.zq.user.config;
import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* @author /
*/
@RequiredArgsConstructor
public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final TokenProvider tokenProvider;
private final SecurityProperties properties;
private final RedisUtils redisUtils;
@Override
public void configure(HttpSecurity http) {
TokenFilter customFilter = new TokenFilter(tokenProvider, properties, redisUtils);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.zq.user.config;
import cn.hutool.core.util.StrUtil;
import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties;
import com.zq.common.context.ContextUtils;
import com.zq.common.vo.OnlineUserDto;
import io.jsonwebtoken.ExpiredJwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;
/**
* @author /
*/
public class TokenFilter extends GenericFilterBean {
private static final Logger log = LoggerFactory.getLogger(TokenFilter.class);
private final TokenProvider tokenProvider;
private final SecurityProperties properties;
private final RedisUtils redisUtils;
/**
* @param tokenProvider Token
* @param properties JWT
* @param redisUtils redis
*/
public TokenFilter(TokenProvider tokenProvider, SecurityProperties properties, RedisUtils redisUtils) {
this.properties = properties;
this.tokenProvider = tokenProvider;
this.redisUtils = redisUtils;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String token = resolveToken(httpServletRequest);
// 对于 Token 为空的不需要去查 Redis
if (StrUtil.isNotBlank(token)) {
OnlineUserDto onlineUserDto = null;
boolean cleanUserCache = false;
try {
onlineUserDto = redisUtils.getObj(properties.getOnlineKey() + token, OnlineUserDto.class);
} catch (ExpiredJwtException e) {
log.error(e.getMessage());
cleanUserCache = true;
} finally {
if (cleanUserCache || Objects.isNull(onlineUserDto)) {
// userCacheClean.cleanUserCache(String.valueOf(tokenProvider.getClaims(token).get(TokenProvider.AUTHORITIES_KEY)));
}
}
if (onlineUserDto != null && StringUtils.hasText(token)) {
Authentication authentication = tokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
// Token 续期
tokenProvider.checkRenewal(token);
// 设置当前用户
ContextUtils.setAdminContext(onlineUserDto);
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
/**
* 初步检测Token
*
* @param request /
* @return /
*/
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(properties.getHeader());
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) {
// 去掉令牌前缀
return bearerToken.replace(properties.getTokenStartWith(), "");
} else {
log.debug("非法Token:{}", bearerToken);
}
return null;
}
}
package com.zq.user.config;/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.SecurityProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* @author /
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class TokenProvider implements InitializingBean {
private final RedisUtils redisUtils;
private final SecurityProperties properties;
public static final String AUTHORITIES_KEY = "auth";
private static Key key;
private static SignatureAlgorithm signatureAlgorithm;
@Override
public void afterPropertiesSet() {
signatureAlgorithm = SignatureAlgorithm.HS512;
byte[] keyBytes = DatatypeConverter.parseBase64Binary(properties.getBase64Secret());
key = new SecretKeySpec(keyBytes, signatureAlgorithm.getJcaName());
}
public static String createToken(Authentication authentication) {
String authorities = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));
return Jwts.builder()
.setSubject(authentication.getName())
.claim(AUTHORITIES_KEY, authorities)
.signWith(signatureAlgorithm, key)
// 加入ID确保生成的 Token 都不一致
.setId(IdUtil.simpleUUID())
.compact();
}
public Claims getClaims(String token) {
return Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret()))
.parseClaimsJws(token)
.getBody();
}
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser()
.setSigningKey(DatatypeConverter.parseBase64Binary(properties.getBase64Secret()))
.parseClaimsJws(token)
.getBody();
// fix bug: 当前用户如果没有任何权限时,在输入用户名后,刷新验证码会抛IllegalArgumentException
Object authoritiesStr = claims.get(AUTHORITIES_KEY);
Collection<? extends GrantedAuthority> authorities =
ObjectUtil.isNotEmpty(authoritiesStr) ?
Arrays.stream(authoritiesStr.toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList()) : Collections.emptyList();
User principal = new User(claims.getSubject(), "******", authorities);
return new UsernamePasswordAuthenticationToken(principal, token, authorities);
}
/**
* @param token 需要检查的token
*/
public void checkRenewal(String token) {
// 判断是否续期token,计算token的过期时间
long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000;
Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
// 判断当前时间与过期时间的时间差
long differ = expireDate.getTime() - System.currentTimeMillis();
// 如果在续期检查的范围内,则续期
if (differ <= properties.getDetect()) {
long renew = time + properties.getRenew();
redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
}
}
public String getToken(HttpServletRequest request) {
String bearerToken = request.getHeader(properties.getHeader());
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) {
// 去掉令牌前缀
return bearerToken.replace(properties.getTokenStartWith(), "");
}
return null;
}
}
......@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
@Api(tags = "用户相关接口")
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/wine/app/user")
@RequestMapping(value = "/user/app/user")
public class UserController {
private final UserService userService;
......
package com.zq.user.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zq.common.entity.Pfuser;
import org.springframework.stereotype.Repository;
/**
* 存放系统所有用户的基本信息(Pfuser)表数据库访问层
*
* @author makejava
* @since 2021-06-23 17:56:31
*/
@Repository
public interface PfuserDao extends BaseMapper<Pfuser> {
}
package com.zq.user.service;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zq.common.config.redis.RedisUtils;
import com.zq.common.config.security.ApiTokenUtils;
import com.zq.common.entity.AppUser;
import com.zq.common.entity.Pfuser;
import com.zq.common.http.HttpRequestUtils;
import com.zq.common.utils.AssertUtils;
import com.zq.common.vo.ApiTokenVo;
import com.zq.user.dao.PfuserDao;
import com.zq.user.dao.UserDao;
import com.zq.user.manager.CacheKeys;
import com.zq.user.vo.LoginVo;
......@@ -25,6 +28,7 @@ import org.springframework.util.DigestUtils;
public class UserService {
private final UserDao userDao;
private final PfuserDao pfuserDao;
private final RedisUtils redisUtils;
/**
......@@ -56,6 +60,35 @@ public class UserService {
userDao.updateById(appUser);
}
public ApiTokenVo phoneLogin(LoginVo vo) {
AppUser appUser = userDao.selectOne(Wrappers.lambdaQuery(AppUser.builder().phone(vo.getPhone()).build()));
if (appUser == null) {
Pfuser pfuser = pfuserDao.selectOne(Wrappers.lambdaQuery(Pfuser.builder().phone(vo.getPhone()).state(0L).build()));
if (pfuser != null) {
appUser = AppUser.builder()
.name(pfuser.getUsername())
.age(pfuser.getSex().intValue())
.phone(pfuser.getPhone())
.userType(pfuser.getType().intValue())
.age(IdcardUtil.getAgeByIdCard(pfuser.getIdcardno()))
.build();
userDao.insert(appUser);
}
}
AssertUtils.notNull(appUser, "用户不存在");
AssertUtils.isTrue(DigestUtils.md5DigestAsHex(vo.getPasswd().getBytes()).equals(appUser.getPassword()), "密码错误");
AssertUtils.isTrue(appUser.getStatus() == 1, appUser.getStatus() == 2 ? "账号已暂停使用" : "账号已冻结");
appUser.setAccessIp(ServletUtil.getClientIP(HttpRequestUtils.getRequest()));
appUser.setLastLoginTime(DateUtil.date());
userDao.updateById(appUser);
return getApiToken(appUser);
}
/**
* 判断验证码
*
......@@ -95,18 +128,4 @@ public class UserService {
return tokenVo;
}
public ApiTokenVo phoneLogin(LoginVo vo) {
AppUser appUser = userDao.selectOne(Wrappers.lambdaQuery(AppUser.builder().phone(vo.getPhone()).build()));
AssertUtils.notNull(appUser, "用户不存在");
AssertUtils.isTrue(DigestUtils.md5DigestAsHex(vo.getPasswd().getBytes()).equals(appUser.getPassword()), "密码错误");
AssertUtils.isTrue(appUser.getStatus() == 1, appUser.getStatus() == 2 ? "账号已暂停使用" : "账号已冻结");
appUser.setAccessIp(ServletUtil.getClientIP(HttpRequestUtils.getRequest()));
appUser.setLastLoginTime(DateUtil.date());
userDao.updateById(appUser);
return getApiToken(appUser);
}
}
server:
port: ${user.port}
#配置数据源
spring:
application:
name: ${user.name}
servlet:
#上传文件限制
multipart:
#单个文件大小
max-file-size: 20MB
#设置总上传的数据大小
max-request-size: 50MB
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
redis:
#数据库索引
database: 0
host: ${redis.url}
port: ${redis.port}
password: ${redis.password}
#连接超时时间
timeout: 5000
datasource:
druid:
db-type: com.alibaba.druid.pool.DruidDataSource
driverClassName: ${jdbc.driver-class-name}
username: ${jdbc.username}
password: ${jdbc.password}
url: ${jdbc.url}
# 初始连接数
initial-size: 5
# 最小连接数
min-idle: 10
# 最大连接数
max-active: 20
# 获取连接超时时间
max-wait: 5000
# 连接有效性检测时间
time-between-eviction-runs-millis: 60000
# 连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
# 连接在池中最大生存的时间
max-evictable-idle-time-millis: 900000
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 检测连接是否有效
validation-query: select 1
# 配置监控统计
webStatFilter:
enabled: true
stat-view-servlet:
enabled: true
url-pattern: /druid/*
reset-enable: false
filter:
stat:
enabled: true
# 记录慢SQL
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# mybatis plus 配置
mybatis-plus:
global-config:
db-config:
select-strategy: not_empty
update-strategy: not_empty
#logging.level.com.zq.drug.dao: debug
spring:
cloud:
config:
name: config
profile: @profiles.active@
discovery:
enabled: true
service-id: CONFIG-SERVER
uri: http://127.0.0.1:8300/
eureka:
client:
serviceUrl:
defaultZone: http://admin:123456@127.0.0.1:8800/eureka/
Markdown is supported
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