pom.xml
@@ -151,12 +151,101 @@ <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> <!--common-codec加密--> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.54</version> </dependency> <!--commons.lang3 RSA签名验证md5使用--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> <!--外部引入-人脸识别sdk--> <!--免费版 V3.0--> <dependency> <groupId>com.whyc</groupId> <artifactId>face</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${pom.basedir}/src/main/resources/lib/arcsoft-sdk-face-3.0.0.0.jar</systemPath> </dependency> <!--增值版 V3.1--> <!--<dependency> <groupId>com.whyc</groupId> <artifactId>face</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${pom.basedir}/src/main/resources/lib/arcsoft-sdk-face-3.1.1.0.jar</systemPath> </dependency>--> <!--<dependency> <groupId>org.tensorflow</groupId> <artifactId>tensorflow</artifactId> <version>1.15.0</version> </dependency>--> <!-- https://mvnrepository.com/artifact/net.sf.jacob-project/jacob --> <dependency> <groupId>net.sf.jacob-project</groupId> <artifactId>jacob</artifactId> <version>1.17-M2</version> <scope>system</scope> <systemPath>${pom.basedir}/src/main/resources/lib/jacob.jar</systemPath> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>0.0.0</version> <scope>system</scope> <systemPath>${pom.basedir}/src/main/resources/lib/tomcat-embed-core-9.0.93.jar</systemPath> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>com.github.oshi</groupId> <artifactId>oshi-core</artifactId> <version>5.6.1</version> <exclusions> <exclusion> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> </exclusion> <exclusion> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.8</version> </dependency> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.4</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.15.0</version> </dependency> </dependencies> <build> <plugins> src/main/java/com/whyc/constant/YamlProperties.java
@@ -22,32 +22,20 @@ public static Integer systemType; /**人脸识别对比阈值*/ //public static Float faceThreshold; public static Float faceThreshold; /**告警短信开关*/ /* public static String messageSwitch; public static String messageSecretId; public static String messageSecretKey; public static String messageRegion; public static String messageSdkAppId; public static String messageSignName; public static String messageTemplateId;*/ /* public static String appId4Win; public static String sdkKey4Win; public static String appId4Linux; public static String sdkKey4Linux;*/ /**告警工单开关*/ //public static String alarmTaskSwitch; /**系统运行模式*/ public static Integer runModel; /**FTP信息*/ /*public static String ftpIp; public static Integer ftpPort; public static String ftpUserName; public static String ftpPassword;*/ public static String appId4Win; public static String sdkKey4Win; public static String appId4Linux; public static String sdkKey4Linux; public static String activeKey; public static Integer faceType; /*====== 自定义信息 ======*/ @@ -80,55 +68,25 @@ public void setSystemType(Integer systemType) { YamlProperties.systemType = systemType; } /* @Value("${custom.face.threshold}") private void setFaceThreshold(Float faceThreshold) { YamlProperties.faceThreshold = faceThreshold; }*/ /* @Value("${custom.message.switch}") private void setMessageSwitch(String messageSwitch) { YamlProperties.messageSwitch = messageSwitch; }*/ /* @Value("${custom.message.secret_id}") private void setMessageSecretId(String messageSecretId) { YamlProperties.messageSecretId = messageSecretId; } */ /*@Value("${custom.message.secret_key}") private void setMessageSecretKey(String messageSecretKey) { YamlProperties.messageSecretKey = messageSecretKey; @Value("${configFile.type}") public void setRunModel(Integer runModel) { YamlProperties.runModel = runModel; } @Value("${custom.message.region}") private void setMessageRegion(String messageRegion) { YamlProperties.messageRegion = messageRegion; @Value("${custom.face.activeKey}") private void setActiveKey(String activeKey) { YamlProperties.activeKey = activeKey; } @Value("${custom.message.smsSdkAppId}") private void setMessageSdkAppId(String messageSdkAppId) { YamlProperties.messageSdkAppId = messageSdkAppId; @Value("${custom.face.type}") public void setFaceType(Integer faceType) { YamlProperties.faceType = faceType; } @Value("${custom.message.signName}") private void setMessageSignName(String messageSignName) { YamlProperties.messageSignName = messageSignName; } @Value("${custom.message.templateId}") private void setMessageTemplateId(String messageTemplateId) { YamlProperties.messageTemplateId = messageTemplateId; }*/ /* @Value("${custom.alarm.task.switch}") private void setAlarmTaskSwitch(String alarmTaskSwitch) { YamlProperties.alarmTaskSwitch = alarmTaskSwitch; } */ /*@Value("${custom.face.appId4Win}") @Value("${custom.face.appId4Win}") private void setAppId4Win(String appId4Win) { YamlProperties.appId4Win = appId4Win; } @@ -146,32 +104,10 @@ @Value("${custom.face.sdkKey4Linux}") private void setSdkKey4Linux(String sdkKey4Linux) { YamlProperties.sdkKey4Linux = sdkKey4Linux; }*/ @Value("${configFile.type}") public void setRunModel(Integer runModel) { YamlProperties.runModel = runModel; } /*@Value("${ftpInforMation.ftpIp}") public void setFtpIp(String ftpIp){ YamlProperties.ftpIp=ftpIp; @Value("${custom.face.threshold}") private void setFaceThreshold(Float faceThreshold) { YamlProperties.faceThreshold = faceThreshold; } @Value("${ftpInforMation.ftpPort}") public void setFtpPort(Integer ftpPort){ YamlProperties.ftpPort=ftpPort; } @Value("${ftpInforMation.ftpUserName}") public void setFtpUserName(String ftpUserName){ YamlProperties.ftpUserName=ftpUserName; } @Value("${ftpInforMation.ftpPassword}") public void setFtpPassword(String ftpPassword){ YamlProperties.ftpPassword=ftpPassword; }*/ } src/main/java/com/whyc/controller/FaceController.java
New file @@ -0,0 +1,411 @@ package com.whyc.controller; import com.arcsoft.face.FaceEngine; import com.arcsoft.face.toolkit.ImageFactory; import com.arcsoft.face.toolkit.ImageInfo; import com.whyc.constant.YamlProperties; import com.whyc.dto.Response; import com.whyc.factory.FaceEngineFactory; import com.whyc.pojo.db_user.UserInf; import com.whyc.service.FaceService; import com.whyc.service.UserInfService; import com.whyc.util.ActionUtil; import com.whyc.util.CommonUtil; import com.whyc.util.FaceIdentifyUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.system.ApplicationHome; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import sun.misc.BASE64Decoder; import javax.annotation.Resource; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 人脸识别 */ @RequestMapping("face") @RestController @Api(tags = "用户管理-人脸识别") public class FaceController { @Resource private FaceService service; @Resource private UserInfService userService; //@Resource //private MapOutlineService mapOutlineService; @GetMapping("activeOnline") @ApiOperation(value = "在线激活人脸识别引擎",notes = "只需要刚开始时调用一次,会导致appId与硬件设备绑定,必须有外部网络,否则激活会失败!" + "后续使用无需再调用激活,可以离线使用") public Response activeOnline(){ boolean b = FaceIdentifyUtil.active(1); if(b){ return new Response().set(1,true,"引擎激活成功"); }else{ return new Response().set(1,false,"引擎激活失败,请检查网络是否为外网并确认appId和key是否正确!"); } } @GetMapping("activeOffline") @ApiOperation(value = "离线激活人脸识别引擎,增值版使用") public Response activeOffline(){ boolean b = FaceIdentifyUtil.active(2); if(b){ return new Response().set(1,true,"引擎激活成功"); }else{ return new Response().set(1,false,"引擎激活失败,请检查网络是否为外网并确认appId和key是否正确!"); } } @PostMapping @ApiOperation(value = "添加",notes = "添加到人脸库") public Response add(@RequestBody Map<String,Object> paramMap ){ String fileData = (String) paramMap.get("fileData"); String uName = (String) paramMap.get("uName"); //过滤 uName的特殊字符,避免路径遍历攻击 uName = ActionUtil.filterFileName(uName); Integer uId = Integer.parseInt((String)paramMap.get("uId")); //传参 uId,uName,fileData--文件流 fileData = fileData.replaceAll(" ", "+"); //由于图片字符串是由base64编码的,解码成字节数组 //data:image/jpeg;base64, // fileData = fileData.replaceAll("data:image/jpeg;base64,",""); fileData = fileData.split(",")[1]; BASE64Decoder decoder = new BASE64Decoder(); byte[] dataBytes = new byte[0]; try { dataBytes = decoder.decodeBuffer(fileData); /*for (int i = 0; i < dataBytes.length; ++i) { if (dataBytes[i] < 0) {// 调整异常数据 dataBytes[i] += 256; } }*/ } catch (IOException e) { e.printStackTrace(); } /*=========检查图片是否有效=======*/ //检验图片是否有效 ImageInfo imageInfo = ImageFactory.getRGBData(dataBytes); //初始化引擎 // FaceEngine faceEngine = FaceIdentifyUtil.init(); FaceEngine faceEngine = FaceEngineFactory.getInstance(); if (faceEngine==null){ return new Response().set(1,false,"初始化引擎失败"); }else { //检查角度是否端正,检查人脸像素大小是否>50×50 Response checkRes1 = FaceIdentifyUtil.orientAndPxDetect(faceEngine,imageInfo); if((boolean)checkRes1.getData()){ /*=========图片保存===========*/ ApplicationHome applicationHome = new ApplicationHome(getClass()); File jarFile = applicationHome.getDir(); //存储人脸图片的文件夹 String fileDirName; if(YamlProperties.runModel == 1) { fileDirName = jarFile.getParentFile().toString() + File.separator + "fg_photo"; }else{ fileDirName = jarFile.toString() + File.separator + "fg_photo"; } File file = new File(fileDirName); //不存在则创建该文件夹 if (!file.exists()) { file.mkdirs(); } //文件全路径 String fileName = fileDirName + File.separator + uName + ".jpg"; FileOutputStream fot=null; try { fot = new FileOutputStream(fileName); fot.write(dataBytes); fot.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if(fot!=null){ try { fot.close(); } catch (IOException e) { e.printStackTrace(); } } } /*=========数据库表更新===========*/ // model = service.add(uId, uName, projectName); service.add(uId, uName, fileName); return new Response().set(1,true,"新增成功"); } return checkRes1; } } /** * 人脸库管理: 更新 * @return */ @PostMapping("update") @ApiOperation(value = "更新") public Response update(@RequestBody String fileData,@RequestParam String uName){ //传参,uName,fileData--文件流 //过滤 uName的特殊字符,避免路径遍历攻击 uName = ActionUtil.filterFileName(uName); //由于图片字符串是由base64编码的,解码成字节数组 fileData = fileData.replaceAll(" ", "+"); fileData = fileData.split(",")[1]; BASE64Decoder decoder = new BASE64Decoder(); byte[] dataBytes = new byte[0]; try { dataBytes = decoder.decodeBuffer(fileData); } catch (IOException e) { e.printStackTrace(); } /*=========检查图片是否有效=======*/ //检验图片是否有效 //获取图像信息 ImageInfo imageInfo = ImageFactory.getRGBData(dataBytes); //初始化引擎 // FaceEngine faceEngine = FaceIdentifyUtil.init(); FaceEngine faceEngine = FaceEngineFactory.getInstance(); if (faceEngine==null){ return new Response().set(1,false,"初始化引擎失败"); }else { //检测图片 Response checkRes1 = FaceIdentifyUtil.orientAndPxDetect(faceEngine, imageInfo); if ((boolean)checkRes1.getData()) { /*=========图片保存===========*/ ApplicationHome applicationHome = new ApplicationHome(getClass()); File jarFile = applicationHome.getDir(); //存储人脸图片的文件夹 String fileDirName; if(YamlProperties.runModel == 1) { fileDirName = jarFile.getParentFile().toString() + File.separator + "fg_photo"; }else{ fileDirName = jarFile.toString() + File.separator + "fg_photo"; } File file = new File(fileDirName); //不存在则创建该文件夹 if (!file.exists()) { file.mkdirs(); } //文件全路径 String fileName = fileDirName + File.separator + uName + ".jpg"; FileOutputStream fot =null; try { fot = new FileOutputStream(fileName); fot.write(dataBytes); fot.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if(fot!=null){ try { fot.close(); } catch (IOException e) { e.printStackTrace(); } } } return new Response().set(1,"更新成功"); } return checkRes1; } } /** * 人脸库管理: 删除 * @return */ @PostMapping("delete") @ApiOperation(value = "删除") @Transactional public Response delete(@RequestParam Integer uId,@RequestParam Integer faceId, @RequestParam String uName,HttpServletRequest request){ //过滤 uName的特殊字符,避免路径遍历攻击 uName = ActionUtil.filterFileName(uName); //更新user_inf和face表 service.update(uId,faceId); //删除图片 //获取到图片所在文件夹的全路径 String fileName = findFileDirPath(request); //获取图片的全路径 File file = new File(fileName+File.separator+uName+".jpg"); if(file.exists()){ file.delete(); } return new Response().set(1,"删除成功"); } /**获取图片文件夹全路径 * @param request*/ private String findFileDirPath(HttpServletRequest request) { ApplicationHome applicationHome = new ApplicationHome(getClass()); File jarFile = applicationHome.getDir(); //在jar包所在目录下生成一个upload文件夹用来存储上传的图片 return jarFile.getParentFile().toString()+File.separator+"fg_photo"; } /**获取图片的http加载url*/ private String findWebPhotoUrl(String uName){ HttpServletRequest request = ActionUtil.getRequest(); //获取项目名称 String realPath = ActionUtil.getApplication().getRealPath("/"); //String[] split = realPath.split("/"); String[] split = realPath.split(File.separator); String projectName = split[split.length - 1]; //图片保存路径,采取ip+port访问形式而非硬盘形式,方便图片加载 String url = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/"+projectName+"_photo/"+uName+".jpg"; return url; } /** * 人脸库管理: 查询分页列表 * 现在逻辑是当前用户查询自己的人脸信息 * @return */ @GetMapping("info") @ApiOperation(value = "查询人脸信息") public Response getInfo(HttpServletRequest request){ //传入pageNum,pageSize UserInf userInf = (UserInf) request.getSession().getAttribute("user"); UserInf user = service.getInfo(userInf.getUid()); return new Response().set(1,user); } /** * 人脸识别: 活体检验,相似度对比,1比N */ @PostMapping("faceCompare2N") @ApiOperation(value = "人脸识别对比") public Response faceCompare2N(@RequestBody String fileData,@RequestParam String uKeyId,HttpServletRequest request){ Response res = new Response(); //先验证uKeyId对应的用户 UserInf userByUKeyId = userService.getUserByUKeyId(uKeyId); if (userByUKeyId == null){ return res.set(1,false,"Ukey没有绑定用户"); } /*====获取图片并校验活体,角度,像素大小====*/ //由于图片字符串是由base64编码的,解码成字节数组 fileData = fileData.replaceAll(" ", "+"); fileData = fileData.split(",")[1]; BASE64Decoder decoder = new BASE64Decoder(); byte[] dataBytes = new byte[0]; try { dataBytes = decoder.decodeBuffer(fileData); } catch (IOException e) { e.printStackTrace(); } ImageInfo imageInfo = ImageFactory.getRGBData(dataBytes); FaceEngine faceEngine = FaceEngineFactory.getInstance(); if(faceEngine!=null) { res = FaceIdentifyUtil.liveDetect(faceEngine, imageInfo); //活体校验通过 if (res.getCode() == 1) { res = FaceIdentifyUtil.orientAndPxDetect(faceEngine, imageInfo); //人像角度,大小校验通过 if((boolean) res.getData()) { //重置标识 res.setData(null); res.setMsg(null); //获取数据库中所有的人脸图片 List<UserInf> userInfList = service.findAllFaceUrl(); if(userInfList.size()==0){ res.setCode(0); res.setMsg("人脸库暂无任何数据"); }else{ boolean urlExist = false; for (UserInf temp:userInfList){ String filePath = temp.getFace().getUrl(); File file = new File(filePath); //不存在则不继续执行 if(!file.exists()){ continue; }else{ urlExist = true; } ImageInfo imageInfo2 = ImageFactory.getRGBData(file); res = FaceIdentifyUtil.faceCompare(faceEngine, imageInfo, imageInfo2); //对比成功,记录用户登录信息 if((boolean) res.getData()){ //Ukey对应用户和人脸对应用户验证 if(!(temp.getUid()==userByUKeyId.getUid())){ return res.set(1,false,"UKey对应用户和当前人脸对应用户不匹配"); } List<Object> dataList = new ArrayList<>(); dataList.add(temp); // 将登陆成功的用户存入session ServletContext servletContext = request.getServletContext(); servletContext.setAttribute(temp.getUname(), request.getSession().getId()); ActionUtil.getSession().setAttribute("user", temp); //设置session不活动时间为30分 ActionUtil.getSession().setMaxInactiveInterval(60 * 30); ActionUtil.getSession().setAttribute("ip", ActionUtil.getRequest().getRemoteAddr()); /* List<PermitGroup> permitList = permitGroupUserService.getPermitByUser(temp.getUId()); if (permitList!=null && permitList.size()!=0) { dataList.add(permitList.get(0).getPermitGroupId()); ActionUtil.getSession().setAttribute("permits", permitList); } else { res.setCode(1); res.setData(false); res.setMsg("还未分配权限"); } */ //查询用户对应的班组标识 //dataList.add(baoJiGroupUserService.getGroupFlag(temp.getUId().intValue())); //查询激活的地图 //String mapName = mapOutlineService.selectMapName(); //dataList.add(mapName); //CommonUtil.record(temp.getUId(), UserOperation.TYPE_LOGIN.getType(), UserOperation.TYPE_LOGIN.getTypeName(), UserOperation.TYPE_LOGIN.getTypeNameEn()); res.setData2(dataList); //将新登录的用户存入application userService.setApplication(temp); } } if(!urlExist){ res.set(1,false,"ukey对应的人脸库路径不存在"); } } } } }else{ res.setCode(0); res.setMsg("初始化引擎失败"); } return res; } } src/main/java/com/whyc/controller/LoginController.java
@@ -47,4 +47,10 @@ return new Response().set(1, true); } @ApiOperation(value = "test测试平台正确性") @GetMapping("test") public Response test() { return new Response().set(1, true); } } src/main/java/com/whyc/dto/Response.java
@@ -14,6 +14,16 @@ private T data4; private T data5; private String msg; public Response<T> setCode(Integer code) { this.code = code; return this; } public Response<T> setData(T data) { this.data = data; return this; } public Response<T> set(Integer code, String msg) { this.code = code; this.msg = msg; src/main/java/com/whyc/factory/FaceEngineFactory.java
New file @@ -0,0 +1,16 @@ package com.whyc.factory; import com.arcsoft.face.FaceEngine; import com.whyc.util.FaceIdentifyUtil; /** * 单例工厂,获取FaceEngine: * 采取恶汉模式 */ public class FaceEngineFactory { private static FaceEngine faceEngine = FaceIdentifyUtil.init(); public static FaceEngine getInstance(){ return faceEngine; } } src/main/java/com/whyc/factory/ThreadPoolExecutorFactory.java
New file @@ -0,0 +1,23 @@ package com.whyc.factory; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ThreadPoolExecutorFactory { private static ThreadPoolExecutor poolExecutor = init(); private static ThreadPoolExecutor init() { //线程池初始化 UserThreadFactory userThreadFactory = new UserThreadFactory("fg"); ThreadPoolExecutor pool = new ThreadPoolExecutor(10, 48, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<>(16), userThreadFactory,new ThreadPoolExecutor.CallerRunsPolicy()); poolExecutor = pool; return pool; } public static ThreadPoolExecutor getPoolExecutor() { return poolExecutor; } } src/main/java/com/whyc/factory/UserThreadFactory.java
New file @@ -0,0 +1,23 @@ package com.whyc.factory; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; public class UserThreadFactory implements ThreadFactory { private final String namePrefix; private final AtomicInteger nextId = new AtomicInteger(1); // 定义线程组名称,在 jstack 问题排查时,非常有帮助 public UserThreadFactory(String whatFeaturOfGroup) { namePrefix = "From UserThreadFactory's " + whatFeaturOfGroup + "-Worker-"; } @Override public Thread newThread(Runnable task) { String name = namePrefix + nextId.getAndIncrement(); return new Thread(task, name); } public static boolean flag = true; } src/main/java/com/whyc/mapper/FaceMapper.java
New file @@ -0,0 +1,14 @@ package com.whyc.mapper; import com.whyc.pojo.db_user.UserInf; import java.util.List; public interface FaceMapper<UserFace> extends CustomMapper<UserFace> { UserInf getInfo(int uId); List<UserInf> findAllFaceUrl(); } src/main/java/com/whyc/pojo/db_user/UserClient.java
New file @@ -0,0 +1,51 @@ package com.whyc.pojo.db_user; public class UserClient { /**客户端ip地址 */ public String ip; /** 客户端用户信息*/ public UserInf user; /** 客户端登录时间的毫秒数*/ public Long login_times; public UserClient() { } public UserClient(String ip, UserInf user) { super(); this.ip = ip; this.user = user; } public UserClient(String ip, UserInf user, Long login_times) { super(); this.ip = ip; this.user = user; this.login_times = login_times; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public UserInf getUser() { return user; } public void setUser(UserInf user) { this.user = user; } public Long getLogin_times() { return login_times; } public void setLogin_times(Long login_times) { this.login_times = login_times; } } src/main/java/com/whyc/pojo/db_user/UserFace.java
New file @@ -0,0 +1,48 @@ package com.whyc.pojo.db_user; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModel; import lombok.Data; import lombok.ToString; /** * 人脸识别 */ @Data @ToString @TableName(schema = "db_user",value = "tb_user_face") @ApiModel(value="UserFace对象", description="") public class UserFace { @TableId private Integer id; /**人脸图片路径,http*/ private String url; public UserFace() { } public UserFace(String url) { this.url = url; } public UserFace(Integer id, String url) { this.id = id; this.url = url; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } src/main/java/com/whyc/pojo/db_user/UserInf.java
@@ -58,12 +58,18 @@ @ApiModelProperty(value = "地址") private String address; @ApiModelProperty(value = "人脸库id") private Integer faceId; @TableField(exist = false) private List<AreaInf> ainfList; @TableField(exist = false) private List<Integer> idList; @TableField(exist = false) private UserFace face; public UserInf(int uid, String uname) { this.uid = uid; src/main/java/com/whyc/service/FaceService.java
New file @@ -0,0 +1,74 @@ package com.whyc.service; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.whyc.mapper.FaceMapper; import com.whyc.mapper.UserInfMapper; import com.whyc.pojo.db_user.UserFace; import com.whyc.pojo.db_user.UserInf; import com.whyc.util.ActionUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.List; @Service public class FaceService { @Resource private FaceMapper mapper; @Resource private UserInfMapper userMapper; /** * 两种分页:mybatis-plus自带和PageHelper的自定义 * @param * @param uId * @return */ /*public List<UserFace> getPage(PageInfo page, int uId) { PageInfo<Face> pageInfo = mapper.findAll(page,uId); model.setCode(1); model.setData(pageInfo); return model; }*/ @Transactional public boolean add(int uId, String uName, String fileName) { //人脸表新增记录 UserFace userFace = new UserFace(fileName); mapper.insert(userFace); //用户表关联新增的人脸表记录id UpdateWrapper<UserInf> wrapper = Wrappers.update(); wrapper.set("face_id",userFace.getId()).eq("uid",uId); userMapper.update((UserInf) ActionUtil.objeNull,wrapper); return true; } /**TODO 待错误测试*/ /**逻辑删除,取消用户与图片的关系*/ public boolean update(int uId,int faceId) { //人脸表删除记录 mapper.deleteById(faceId); //用户表关联新增的人脸表记录id UpdateWrapper<UserInf> wrapper = Wrappers.update(); wrapper.set("face_id",null).eq("uId",uId); userMapper.update((UserInf) ActionUtil.objeNull,wrapper); return true; } public UserInf getInfo(int uId) { return mapper.getInfo(uId); } public List<UserInf> findAllFaceUrl() { return mapper.findAllFaceUrl(); } } src/main/java/com/whyc/service/UserInfService.java
@@ -8,10 +8,10 @@ import com.whyc.dto.Response; import com.whyc.mapper.*; import com.whyc.pojo.db_area.*; import com.whyc.pojo.db_user.UserClient; import com.whyc.pojo.db_user.UserInf; import com.whyc.util.ActionUtil; import com.whyc.util.MD5Util; import com.whyc.util.PageInfoUtils; import com.whyc.util.RSAUtil; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UnknownAccountException; @@ -20,14 +20,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.*; import java.util.stream.Collectors; @Service @@ -373,4 +370,31 @@ } return new Response().set(1,true,"编辑用户信息成功"); } public UserInf getUserByUKeyId(String uKeyId){ QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("uKey_ID",uKeyId); UserInf userInf = mapper.selectOne(queryWrapper); return userInf; } // 将所有登陆的用户的信息存到application中 public void setApplication(UserInf user) { ServletContext application = ActionUtil.getApplication(); //查看全局中存储的users的Map的key-value集合 Map<String, UserClient> map = (Map) application.getAttribute("users"); if (map == ActionUtil.objeNull) { map = new HashMap<String, UserClient>(); } else { //如果集合中有值,则获取当前用户对应的用户信息,key为用户名username,Value为用户名,存储的时间 UserClient client = map.get(user.getUname()); if (client != ActionUtil.objeNull) { //已存在 map.remove(user.getUname()); } } Long login_time = new Date().getTime(); ActionUtil.getSession().setAttribute("login_time", login_time); map.put(user.getUname(), new UserClient(ActionUtil.getRequest().getRemoteAddr(),user,login_time)); application.setAttribute("users", map); } } src/main/java/com/whyc/util/CommonUtil.java
@@ -1,7 +1,13 @@ package com.whyc.util; import com.whyc.constant.YamlProperties; import com.whyc.pojo.db_user.UserInf; import com.whyc.service.OperationLogService; import org.springframework.boot.system.ApplicationHome; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.io.File; /** * 通用工具列 @@ -31,6 +37,48 @@ service.record(type1, type2, msg, msgDetail); } /**获取当前Session中的属性user*/ public static UserInf getUser(HttpServletRequest request) { return (UserInf) request.getSession().getAttribute("user"); } public static String classesPath(){ ApplicationHome applicationHome = new ApplicationHome(CommonUtil.class); File jarFile = applicationHome.getDir(); return jarFile.toString(); } public static String getRootFile(){ ApplicationHome applicationHome = new ApplicationHome(CommonUtil.class); File jarFile = applicationHome.getDir(); String baseDirPath; if(YamlProperties.runModel == 1) { //开发路径 baseDirPath = jarFile.getParentFile().toString()+File.separator+"fg_file"+File.separator; }else { //打包路径 baseDirPath = jarFile.toString()+File.separator+"fg_file"+File.separator; } return baseDirPath; } /** * 获取项目所在文件夹路径 * @return 获取项目所在文件夹路径 */ public static String getProjectDir(){ ApplicationHome applicationHome = new ApplicationHome(CommonUtil.class); File jarFile = applicationHome.getDir(); String baseDirPath; if (YamlProperties.runModel == 1) { //开发路径 baseDirPath = jarFile.getParentFile().toString(); } else { //打包路径 baseDirPath = jarFile.toString(); } return baseDirPath; } src/main/java/com/whyc/util/FaceIdentifyUtil.java
New file @@ -0,0 +1,243 @@ package com.whyc.util; import com.arcsoft.face.*; import com.arcsoft.face.enums.DetectMode; import com.arcsoft.face.enums.DetectOrient; import com.arcsoft.face.enums.ErrorInfo; import com.arcsoft.face.toolkit.ImageInfo; import com.whyc.constant.YamlProperties; import com.whyc.dto.Response; import java.io.File; import java.util.ArrayList; import java.util.List; /** * @Description : 虹软人脸识别工具类 * @date 2020/10/28 **/ public class FaceIdentifyUtil { //外网激活 public static boolean active(int activeType){ boolean res = false; String appId=""; String sdkKey=""; String activeKey = YamlProperties.activeKey; Integer faceType = YamlProperties.faceType; FaceEngine faceEngine =null; /*//从官网我的应用中获取 String appId4Win = "AafPX5afzycEnTqH3v79gY3VozNVTSNqT8kzSmP7b48q"; String sdkKey4Win = "GsYwWhxzuQEE1WE34J3Fo8d2QppjkqYGojyc4625JhKb"; //Linux系统appId和sdkKey及文件加载 String appId4Linux ="AafPX5afzycEnTqH3v79gY3VozNVTSNqT8kzSmP7b48q"; String sdkKey4Linux ="GsYwWhxzuQEE1WE34J3Fo8d2GiFdddqH81ghetQQTGmv";*/ //从官网我的应用中获取 String appId4Win = YamlProperties.appId4Win; String sdkKey4Win = YamlProperties.sdkKey4Win; //Linux系统appId和sdkKey及文件加载 String appId4Linux =YamlProperties.appId4Linux; String sdkKey4Linux =YamlProperties.sdkKey4Linux; //String realPath = ActionUtil.getApplication().getRealPath("/"); String realPath = CommonUtil.classesPath(); System.out.println("========realPath=========:"+realPath); System.out.println("========faceEngine dll 路径=========:"+realPath+ File.separator+"lib"+File.separator+"WIN64"); //FaceEngine获取,判断是什么系统和什么版本 if(System.getProperty("os.name").toLowerCase().contains("window")){ appId = appId4Win; sdkKey = sdkKey4Win; if(faceType == 1 //免费版 ) { faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "WIN64"); }else{ //付费版永久 faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "WIN64PRO"); } }else{ appId=appId4Linux; sdkKey=sdkKey4Linux; if(faceType == 1 //免费版 ) { faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "LINUX64"); }else{ //付费版永久 faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "LINUX64PRO"); } } //激活引擎,只需一次就行,后续无需再激活 int errorCode = 666; /**========需要免费版的依赖包才能调用 Start========*/ errorCode = faceEngine.activeOnline(appId, sdkKey); /**========需要免费版的依赖包才能调用 End========*/ /**========需要增值版的依赖包才能调用 Start========*/ /*if(activeType == 1){ //在线激活 errorCode = faceEngine.activeOnline(appId,sdkKey,activeKey); }else if(activeType == 2){ //离线激活 //先服务器生成离线授权文件,离线.dat文件放在 lib下即可 errorCode = faceEngine.activeOffline(realPath + File.separator + "lib" + File.separator + activeKey+".dat"); }*/ /**========需要增值版的依赖包才能调用 End========*/ if (errorCode != ErrorInfo.MOK.getValue() && errorCode != ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue()) { //激活失败 }else{ res=true; } return res; } /**初始化*/ public static FaceEngine init(){ FaceEngine faceEngine=null; String realPath = CommonUtil.classesPath(); if(System.getProperty("os.name").toLowerCase().contains("window")) { if(YamlProperties.faceType == 1 //免费版 ) { faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "WIN64"); }else{ //付费版永久 faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "WIN64PRO"); } }else{ if(YamlProperties.faceType == 1 //免费版 ) { faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "LINUX64"); }else{ //付费版永久 faceEngine = new FaceEngine(realPath + File.separator + "lib" + File.separator + "LINUX64PRO"); } } //引擎配置 EngineConfiguration engineConfiguration = new EngineConfiguration(); engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE); //对特定场景推荐单一角度而非全角度,那样精度更高 engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT); //最多支持的人脸数量 // engineConfiguration.setDetectFaceMaxNum(10); engineConfiguration.setDetectFaceMaxNum(1); engineConfiguration.setDetectFaceScaleVal(16); //功能配置 FunctionConfiguration functionConfiguration = new FunctionConfiguration(); // functionConfiguration.setSupportAge(true); functionConfiguration.setSupportFace3dAngle(true); functionConfiguration.setSupportFaceDetect(true); functionConfiguration.setSupportFaceRecognition(true); // functionConfiguration.setSupportGender(true); functionConfiguration.setSupportLiveness(true); // functionConfiguration.setSupportIRLiveness(true); engineConfiguration.setFunctionConfiguration(functionConfiguration); //初始化引擎 int errorCode = faceEngine.init(engineConfiguration); if (errorCode != ErrorInfo.MOK.getValue()) { String errorCodeStr = ErrorInfo.getValidEnum(errorCode).name(); System.out.println("初始化引擎失败,错误码:"+errorCode+",错误码解释:"+errorCodeStr); return null; } System.out.println("初始化faceEngine引擎成功"); return faceEngine; } public static Response orientAndPxDetect(FaceEngine faceEngine, ImageInfo imageInfo) { //检查角度是否端正,检查人脸像素大小是否>50×50 List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>(); faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList); if (faceInfoList.size()<1){ return new Response().set(1,false,"无效的人脸信息"); }else { FaceInfo faceInfo = faceInfoList.get(0); Rect rect = faceInfo.getRect(); if (faceInfo.getOrient() != 1) { return new Response().set(1,false,"人像姿势不端正"); } else if ((rect.bottom - rect.top) < 50 || (rect.right - rect.left) < 50) { return new Response().set(1,false,"人像面部像素太低"); } } return new Response().set(1,true,"校验通过"); } public static Response liveDetect(FaceEngine faceEngine, ImageInfo imageInfo) { Response res = new Response(); int errorCode=0; List<FaceInfo> faceInfoList = new ArrayList<>(); List<LivenessInfo> livenessInfoList = new ArrayList<>(); errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList); //设置活体测试 //活体取值范围为[0~1],推荐阈值如下,高于此阈值的即可判断为活体。 // RGB 活体:0.5 // IR 活体:0.7 errorCode = faceEngine.setLivenessParam(0.5f, 0.7f); //人脸属性检测 FunctionConfiguration configuration = new FunctionConfiguration(); // configuration.setSupportAge(true); configuration.setSupportFace3dAngle(true); // configuration.setSupportGender(true); configuration.setSupportLiveness(true); errorCode = faceEngine.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, configuration); faceEngine.getLiveness(livenessInfoList); if(livenessInfoList.size()<1 || livenessInfoList.get(0).getLiveness()!=1){ res.setCode(0); res.setMsg("无效的脸部信息"); }else{ res.setCode(1); } return res; } public static Response faceCompare(FaceEngine faceEngine, ImageInfo imageInfo, ImageInfo imageInfo2) { Response res = new Response(); int errorCode=0; //人脸检测 List<FaceInfo> faceInfoList = new ArrayList<>(); errorCode = faceEngine.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList); //特征提取 FaceFeature faceFeature = new FaceFeature(); errorCode = faceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature); //人脸检测2 List<FaceInfo> faceInfoList2 = new ArrayList<>(); errorCode = faceEngine.detectFaces(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(),imageInfo2.getImageFormat(), faceInfoList2); //特征提取2 FaceFeature faceFeature2 = new FaceFeature(); errorCode = faceEngine.extractFaceFeature(imageInfo2.getImageData(), imageInfo2.getWidth(), imageInfo2.getHeight(), imageInfo2.getImageFormat(), faceInfoList2.get(0), faceFeature2); //特征比对 FaceFeature targetFaceFeature = new FaceFeature(); targetFaceFeature.setFeatureData(faceFeature.getFeatureData()); FaceFeature sourceFaceFeature = new FaceFeature(); sourceFaceFeature.setFeatureData(faceFeature2.getFeatureData()); FaceSimilar faceSimilar = new FaceSimilar(); errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar); //官方建议: //人脸比对取值范围为[0~1],推荐阈值如下,高于此阈值的即可判断为同一人。 // 用于生活照之间的特征比对,推荐阈值0.80 // 用于证件照或生活照与证件照之间的特征比对,推荐阈值0.82 float faceThreshold = YamlProperties.faceThreshold; if(faceSimilar.getScore()<faceThreshold){ res.setCode(1); res.setData(false); res.setMsg("人脸不匹配"); }else{ res.setCode(1); res.setData(true); res.setMsg("匹配成功"); } return res; } } src/main/resources/config/application-dev.yml
@@ -62,6 +62,16 @@ algorithm: PBEWithMD5AndDES iv-generator-classname: org.jasypt.iv.NoIvGenerator custom: #人脸 face: #type=1 免费版,type=2 增值版永久 type: 1 threshold: 0.8 appId4Win: 9yyDc1NXJsSQBdareYkBHA8Z4XDvSNkKAibxSmiYhA39 sdkKey4Win: GHmUteeWmeLCRZstetQfXgJTB29wenDazF3UrH85K9hw appId4Linux: AafPX5afzycEnTqH3v79gY3VozNVTSNqT8kzSmP7b48q sdkKey4Linux: GsYwWhxzuQEE1WE34J3Fo8d2GiFdddqH81ghetQQTGmv activeKey: 8611-11H3-Z13R-7HL1 #告警工单 alarm: task.switch: off src/main/resources/config/application-prod-ssl.yml
@@ -28,7 +28,7 @@ datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3382/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true url: jdbc:mysql://192.168.10.82:3382/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true username: root password: Hdw8688139 maxIdel: 60 @@ -73,6 +73,16 @@ algorithm: PBEWithMD5AndDES iv-generator-classname: org.jasypt.iv.NoIvGenerator custom: #人脸 face: #type=1 免费版,type=2 增值版永久 type: 1 threshold: 0.8 appId4Win: 9yyDc1NXJsSQBdareYkBHA8Z4XDvSNkKAibxSmiYhA39 sdkKey4Win: GHmUteeWmeLCRZstetQfXgJTB29wenDazF3UrH85K9hw appId4Linux: AafPX5afzycEnTqH3v79gY3VozNVTSNqT8kzSmP7b48q sdkKey4Linux: GsYwWhxzuQEE1WE34J3Fo8d2GiFdddqH81ghetQQTGmv activeKey: 8611-11H3-Z13R-7HL1 #告警工单 alarm: task.switch: off src/main/resources/config/application-prod.yml
@@ -18,6 +18,7 @@ type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3382/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true # url: jdbc:mysql://192.168.10.82:3382/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowMultiQueries=true&rewriteBatchedStatements=true username: root password: Hdw8688139 maxIdel: 60 @@ -62,11 +63,21 @@ algorithm: PBEWithMD5AndDES iv-generator-classname: org.jasypt.iv.NoIvGenerator custom: #人脸 face: #type=1 免费版,type=2 增值版永久 type: 1 threshold: 0.8 appId4Win: 9yyDc1NXJsSQBdareYkBHA8Z4XDvSNkKAibxSmiYhA39 sdkKey4Win: GHmUteeWmeLCRZstetQfXgJTB29wenDazF3UrH85K9hw appId4Linux: AafPX5afzycEnTqH3v79gY3VozNVTSNqT8kzSmP7b48q sdkKey4Linux: GsYwWhxzuQEE1WE34J3Fo8d2GiFdddqH81ghetQQTGmv activeKey: 8611-11H3-Z13R-7HL1 #告警工单 alarm: task.switch: off #允许跨域的白名单 http://192.168.10.132:8080,http://192.168.10.109:8080 cors: http://localhost:8098,http://192.168.10.133:8098 cors: http://192.168.10.86:8001,http://localhost:8001 rsa: #publicKey: ENC(ZCCRYK0TIFYCrdHZprQS0I8hWFD1uXKIRYcfwDkh3V87FjFePAWlWIzi6tJFcswo525c+m5UGmkt+eq/wCIIabjbcbt6l+18hz6ogtGXHTalaEATqjbrjWmbdzc92A6dYmoNI5Rdpi+jqBKciXZhDKWDNPY2M3/WyejcPGDOeo9CWOvR1hdmLX8iTlcuPRS6k7YzybGZwP9cOHfcAyt6QN+GSuNRzapo5pUmQdT7aUwF3P73qcoxHpRO1li6kYF9KVOMgVix8a3h6TyFMMuJdPGboRV8DL9wLK3bnJT6s0Ei35niYv4ePJ7IzHiEa4J1x0wo8pNU0CfdhylySWLsnxgFjzbhMWjmoQhwQjjnTj+DgyvRrZqaE3R0cLpSwxT4x2ceHzKm1KUzF7OhGgnmc3lPN3H8UyVHy+l3GyejGpRnqFtABHqIlbM2nbsTA8lT/sAeN/AVlBORNgd5Rai7upWk43pvd2qG9ykSW+t/++ZiKBXfAZOBgrcWhPseEG94e3bHhM62nwcgHZ5HzFCZ8PEwXn0053vbxdM6LxVIqCAIzrWoOgBWoaRRBqfSUTvJf2tdc5m9NncXRmYEzZOg3f1wOvVGDJeyKC3OuyhlJnD2VWYVwNsorDkI+dT9mPAMMTZaPeqwPGxtkjaaFSgB5RDHcBfeEIMNdAVOqMCA9qOLFX+zr9mHvjV1kpiDKb5JZFhLHlXObROUtqMndTQDRCATBjutLB4QS0/0BCOvSLnDTA39e/nVKBwTHPqnlz4N) #privateKey: ENC(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) src/main/resources/lib/8611-11H3-Z13R-7HL1.dat
src/main/resources/lib/LINUX64/libarcsoft_face.soBinary files differ
src/main/resources/lib/LINUX64/libarcsoft_face_engine.soBinary files differ
src/main/resources/lib/LINUX64/libarcsoft_face_engine_jni.soBinary files differ
src/main/resources/lib/LINUX64PRO/libarcsoft_face.soBinary files differ
src/main/resources/lib/LINUX64PRO/libarcsoft_face_engine.soBinary files differ
src/main/resources/lib/LINUX64PRO/libarcsoft_face_engine_jni.soBinary files differ
src/main/resources/lib/WIN64/libarcsoft_face.dllBinary files differ
src/main/resources/lib/WIN64/libarcsoft_face_engine.dllBinary files differ
src/main/resources/lib/WIN64/libarcsoft_face_engine_jni.dllBinary files differ
src/main/resources/lib/WIN64PRO/libarcsoft_face.dllBinary files differ
src/main/resources/lib/WIN64PRO/libarcsoft_face_engine.dllBinary files differ
src/main/resources/lib/WIN64PRO/libarcsoft_face_engine_jni.dllBinary files differ
src/main/resources/lib/arcsoft-sdk-face-3.0.0.0.jarBinary files differ
src/main/resources/lib/arcsoft-sdk-face-3.1.1.0.jarBinary files differ
src/main/resources/lib/jacob.jarBinary files differ
src/main/resources/lib/tomcat-embed-core-9.0.30.jarBinary files differ
src/main/resources/lib/tomcat-embed-core-9.0.93.jarBinary files differ
src/main/resources/mapper/FaceMapper.xml
New file @@ -0,0 +1,35 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.whyc.mapper.FaceMapper" > <resultMap id="Map_UserInf" type="UserInf"> <id property="uid" column="uid" /> <result property="uname" column="uname"/> <association property="face" javaType="UserFace"> <id property="id" column="faceId" jdbcType="INTEGER"/> <result property="url" column="faceUrl" jdbcType="VARCHAR"/> </association> </resultMap> <resultMap id="Map_UserInf2" type="UserInf"> <id property="uid" column="uId" /> <result property="uname" column="uName"/> <result property="usnid" column="uSnId"/> <result property="urole" column="uRole"/> <association property="face" javaType="UserFace"> <result property="url" column="url" /> </association> </resultMap> <update id="initDB"> </update> <select id="getInfo" resultMap="Map_UserInf"> select inf.uid,inf.uname,face.id faceId,face.url faceUrl from db_user.tb_user_inf inf left join db_user.tb_user_face face on inf.face_id=face.id where uId=#{uId} limit 1 </select> <select id="findAllFaceUrl" resultMap="Map_UserInf2"> select inf.uname,inf.uid,inf.usnid,inf.urole,face.url from db_user.tb_user_inf inf inner join db_user.tb_user_face face on inf.face_id=face.id </select> </mapper>