学习内容:实现注册超级管理员、RBAC权限模型、封装小程序全局路径何Ajax请求、超级管理员登录、对象云存储、首页部分功能、人脸签到页面
目录结构(只展示有改动的代码)
JwtUtil
package com.example.emos.wx.config.shiro; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateUtil; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Date; @Component @Slf4j public class JwtUtil { @Value("${emos.jwt.secret}") private String secret; @Value("${emos.jwt.expire}") private int expire; public String createToken(int userId){ Date date = DateUtil.offset(new Date(), DateField.DAY_OF_YEAR,5); Algorithm algorithm = Algorithm.HMAC256(secret); JWTCreator.Builder builder = JWT.create(); String token = builder.withClaim("userId",userId).withExpiresAt(date).sign(algorithm); return token; } public int getUserId(String token){ DecodedJWT jwt = JWT.decode(token); int userId = jwt.getClaim("userId").asInt(); return userId; } public void verifierToken(String token){ Algorithm algorithm = Algorithm.HMAC256(secret); JWTVerifier verifier = JWT.require(algorithm).build(); verifier.verify(token); } }
OAuth2Filter
package com.example.emos.wx.config.shiro; import cn.hutool.core.util.StrUtil; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.exceptions.TokenExpiredException; import org.apache.http.HttpStatus; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.web.filter.authc.AuthenticatingFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.concurrent.TimeUnit; @Component @Scope("prototype") public class OAuth2Filter extends AuthenticatingFilter { @Autowired private ThreadLocalToken threadLocalToken; @Value("${emos.jwt.cache-expire}") private int cacheExpire; @Autowired private JwtUtil jwtUtil; @Autowired private RedisTemplate redisTemplate; @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest req = (HttpServletRequest) request; String token = getRequestToken(req); if(StrUtil.isBlank(token)){ return null; } return new OAuth2Token(token); } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { HttpServletRequest req = (HttpServletRequest) request; if(req.getMethod().equals(RequestMethod.OPTIONS.name())){ return true; } return false; } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; resp.setContentType("text/html"); resp.setCharacterEncoding("UTF-8"); resp.setHeader("Access-Control-Allow-Credentials", "true"); resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); threadLocalToken.clear(); String token = getRequestToken(req); if(StrUtil.isBlank(token)){ resp.setStatus(HttpStatus.SC_UNAUTHORIZED); resp.getWriter().print("无效的令牌"); return false; } try{ jwtUtil.verifierToken(token); }catch (TokenExpiredException e){ if(redisTemplate.hasKey(token)){ redisTemplate.delete(token); int userId = jwtUtil.getUserId(token); token = jwtUtil.createToken(userId); redisTemplate.opsForValue().set(token,userId+"",cacheExpire, TimeUnit.DAYS); threadLocalToken.setToken(token); } else{ resp.setStatus(HttpStatus.SC_UNAUTHORIZED); resp.getWriter().print("令牌已过期"); return false; } }catch (Exception e){ resp.setStatus(HttpStatus.SC_UNAUTHORIZED); resp.getWriter().print("无效的令牌"); return false; } boolean bool = executeLogin(request,response); return bool; } @Override protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; resp.setContentType("text/html"); resp.setCharacterEncoding("UTF-8"); resp.setHeader("Access-Control-Allow-Credentials", "true"); resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); resp.setStatus(HttpStatus.SC_UNAUTHORIZED); try{ resp.getWriter().print(e.getMessage()); }catch (Exception exception){ } return false; } @Override public void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; resp.setContentType("text/html"); resp.setCharacterEncoding("UTF-8"); resp.setHeader("Access-Control-Allow-Credentials", "true"); resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); super.doFilterInternal(request, response, chain); } private String getRequestToken(HttpServletRequest request){ String token = request.getHeader("token"); if(StrUtil.isBlank(token)){ token = request.getParameter("token"); } return token; } }
OAuth2Realm
package com.example.emos.wx.config.shiro; import com.example.emos.wx.db.pojo.TbUser; import com.example.emos.wx.service.UserService; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Set; @Component public class OAuth2Realm extends AuthorizingRealm { @Autowired private JwtUtil jwtUtil; @Autowired private UserService userService; @Override public boolean supports(AuthenticationToken token) { return token instanceof OAuth2Token; } /** * 授权(验证权限时调用) */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection collection) { TbUser user = (TbUser) collection.getPrimaryPrincipal(); int userId = user.getId(); Set<String> permsSet = userService.searchUserPermissions(userId); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setStringPermissions(permsSet); return info; } /** * 认证(验证登录时调用) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String accessToken = (String)token.getPrincipal(); int userId = jwtUtil.getUserId(accessToken); TbUser user = userService.searchById(userId); if(user == null){ throw new LockedAccountException("账号已被锁定,请联系管理员"); } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,accessToken,getName()); // SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(); return info; } }
ShiroConfig
package com.example.emos.wx.config.shiro; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.Filter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { @Bean("securityManager") public SecurityManager securityManager(OAuth2Realm realm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm); securityManager.setRememberMeManager(null); return securityManager; } @Bean("shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager,OAuth2Filter filter){ ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); Map<String , Filter> map = new HashMap<>(); map.put("oauth2",filter); shiroFilter.setFilters(map); Map<String,String> filterMap = new LinkedHashMap<>(); filterMap.put("/webjars/**", "anon"); filterMap.put("/druid/**", "anon"); filterMap.put("/app/**", "anon"); filterMap.put("/sys/login", "anon"); filterMap.put("/swagger/**", "anon"); filterMap.put("/v2/api-docs", "anon"); filterMap.put("/swagger-ui.html", "anon"); filterMap.put("/swagger-resources/**", "anon"); filterMap.put("/captcha.jpg", "anon"); filterMap.put("/user/register", "anon"); filterMap.put("/user/login", "anon"); filterMap.put("/test/**", "anon"); filterMap.put("/meeting/recieveNotify", "anon"); filterMap.put("/**", "oauth2"); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; } @Bean("lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){ return new LifecycleBeanPostProcessor(); } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } }
ExceptionAdvice
package com.example.emos.wx.config; import com.example.emos.wx.exception.EmosException; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authz.UnauthorizedException; import org.springframework.http.HttpStatus; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; @Slf4j @RestControllerAdvice public class ExceptionAdvice { @ResponseBody @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Exception.class) public String exceptionHandler(Exception e){ log.error("执行异常",e); if(e instanceof MethodArgumentNotValidException){ MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e; return exception.getBindingResult().getFieldError().getDefaultMessage(); } else if(e instanceof EmosException){ EmosException exception = (EmosException) e; return exception.getMsg(); } else if(e instanceof UnauthorizedException){ return "你不具备相关权限"; } else{ return "后端执行异常"; } } }
SystemConstants
package com.example.emos.wx.config; import lombok.Data; import org.springframework.stereotype.Component; @Data @Component public class SystemConstants { public String attendanceStartTime; public String attendanceTime; public String attendanceEndTime; public String closingStartTime; public String closingTime; public String closingEndTime; }
LoginForm
package com.example.emos.wx.controller.form; import io.swagger.annotations.ApiModel; import lombok.Data; import javax.validation.constraints.NotBlank; @Data @ApiModel public class LoginForm { @NotBlank(message = "临时授权不能为空") private String code; }
RegisterForm
package com.example.emos.wx.controller.form; import io.swagger.annotations.ApiModel; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; @Data @ApiModel public class RegisterForm { @NotBlank(message = "注册码不能为空") @Pattern(regexp = "^[0-9]{6}$",message = "注册码必须是6位数字") private String registerCode; @NotBlank(message = "微信临时授权不能为空") private String code; @NotBlank(message = "昵称不能为空") private String nickname; @NotBlank(message = "头像不能为空") private String photo; }
CheckinController
package com.example.emos.wx.controller; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import com.example.emos.wx.common.util.R; import com.example.emos.wx.config.SystemConstants; import com.example.emos.wx.config.shiro.JwtUtil; //import com.example.emos.wx.controller.form.CheckinForm; //import com.example.emos.wx.controller.form.SearchMonthCheckinForm; import com.example.emos.wx.exception.EmosException; import com.example.emos.wx.service.CheckinService; import com.example.emos.wx.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.validation.Valid; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; @RequestMapping("/checkin") @RestController @Api("签到模块Web接口") @Slf4j public class CheckinController { @Autowired private JwtUtil jwtUtil; // @Value("${emos.image-folder}") // private String imageFolder; @Autowired private CheckinService checkinService; // @Autowired // private UserService userService; // // @Autowired // private SystemConstants constants; @GetMapping("/validCanCheckIn") @ApiOperation("查看用户今天是否可以签到") public R validCanCheckIn(@RequestHeader("token") String token){ int userId=jwtUtil.getUserId(token); String result=checkinService.validCanCheckIn(userId, DateUtil.today()); return R.ok(result); } // @PostMapping("/checkin") // @ApiOperation("签到") // public R checkin(@Valid CheckinForm form,@RequestParam("photo") MultipartFile file,@RequestHeader("token") String token){ // if(file==null){ // return R.error("没有上传文件"); // } // int userId=jwtUtil.getUserId(token); // String fileName=file.getOriginalFilename().toLowerCase(); // if(!fileName.endsWith(".jpg")){ // return R.error("必须提交JPG格式图片"); // } // else{ // String path=imageFolder+"/"+fileName; // try{ // file.transferTo(Paths.get(path)); // HashMap param=new HashMap(); // param.put("userId",userId); // param.put("path",path); // param.put("city",form.getCity()); // param.put("district",form.getDistrict()); // param.put("address",form.getAddress()); // param.put("country",form.getCountry()); // param.put("province",form.getProvince()); // checkinService.checkin(param); // return R.ok("签到成功"); // }catch (IOException e){ // log.error(e.getMessage(),e); // throw new EmosException("图片保存错误"); // } // finally { // FileUtil.del(path); // } // // } // } // // @PostMapping("/createFaceModel") // @ApiOperation("创建人脸模型") // public R createFaceModel(@RequestParam("photo") MultipartFile file,@RequestHeader("token") String token){ // if(file==null){ // return R.error("没有上传文件"); // } // int userId=jwtUtil.getUserId(token); // String fileName=file.getOriginalFilename().toLowerCase(); // if(!fileName.endsWith(".jpg")){ // return R.error("必须提交JPG格式图片"); // } // else{ // String path=imageFolder+"/"+fileName; // try{ // file.transferTo(Paths.get(path)); // checkinService.createFaceModel(userId,path); // return R.ok("人脸建模成功"); // }catch (IOException e){ // log.error(e.getMessage(),e); // throw new EmosException("图片保存错误"); // } // finally { // FileUtil.del(path); // } // // } // } // // @GetMapping("/searchTodayCheckin") // @ApiOperation("查询用户当日签到数据") // public R searchTodayCheckin(@RequestHeader("token") String token){ // int userId=jwtUtil.getUserId(token); // HashMap map=checkinService.searchTodayCheckin(userId); // map.put("attendanceTime",constants.attendanceTime); // map.put("closingTime",constants.closingTime); // long days=checkinService.searchCheckinDays(userId); // map.put("checkinDays",days); // // DateTime hiredate=DateUtil.parse(userService.searchUserHiredate(userId)); // DateTime startDate=DateUtil.beginOfWeek(DateUtil.date()); // if(startDate.isBefore(hiredate)){ // startDate=hiredate; // } // DateTime endDate=DateUtil.endOfWeek(DateUtil.date()); // HashMap param=new HashMap(); // param.put("startDate",startDate.toString()); // param.put("endDate",endDate.toString()); // param.put("userId",userId); // ArrayList<HashMap> list=checkinService.searchWeekCheckin(param); // map.put("weekCheckin",list); // return R.ok().put("result",map); // } // // @PostMapping("/searchMonthCheckin") // @ApiOperation("查询用户某月签到数据") // public R searchMonthCheckin(@Valid @RequestBody SearchMonthCheckinForm form,@RequestHeader("token") String token){ // int userId=jwtUtil.getUserId(token); // DateTime hiredate=DateUtil.parse(userService.searchUserHiredate(userId)); // String month=form.getMonth()<10?"0"+form.getMonth():form.getMonth().toString(); // DateTime startDate=DateUtil.parse(form.getYear()+"-"+month+"-01"); // if(startDate.isBefore(DateUtil.beginOfMonth(hiredate))){ // throw new EmosException("只能查询考勤之后日期的数据"); // } // if(startDate.isBefore(hiredate)){ // startDate=hiredate; // } // DateTime endDate=DateUtil.endOfMonth(startDate); // HashMap param=new HashMap(); // param.put("userId",userId); // param.put("startDate",startDate.toString()); // param.put("endDate",endDate.toString()); // ArrayList<HashMap> list=checkinService.searchMonthCheckin(param); // int sum_1=0,sum_2=0,sum_3=0; // for(HashMap<String,String> one:list){ // String type=one.get("type"); // String status=one.get("status"); // if("工作日".equals(type)){ // if("正常".equals(status)){ // sum_1++; // } // else if("迟到".equals(status)){ // sum_2++; // } // else if("缺勤".equals(status)){ // sum_3++; // } // } // } // return R.ok().put("list",list).put("sum_1",sum_1).put("sum_2",sum_2).put("sum_3",sum_3); // } }
TestController
package com.example.emos.wx.controller; import com.example.emos.wx.common.util.R; import com.example.emos.wx.controller.form.TestSayHelloForm; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; @RestController @RequestMapping("/test") @Api("测试Web接口") public class TestController { @PostMapping("/sayHello") @ApiOperation("最简单的测试方法") public R sayHello(@Valid @RequestBody TestSayHelloForm form) { return R.ok().put("message", "Hello,"+form.getName()); } @GetMapping("/hi") public R hi(){ return R.ok(); } @PostMapping("/addUser") @ApiOperation("添加用户") @RequiresPermissions(value = {"A","B"},logical = Logical.OR) public R addUser(){ return R.ok("用户添加成功"); } }
UserController
package com.example.emos.wx.controller; import cn.hutool.json.JSONUtil; import com.example.emos.wx.common.util.R; import com.example.emos.wx.config.shiro.JwtUtil; //import com.example.emos.wx.config.tencent.TLSSigAPIv2; import com.example.emos.wx.controller.form.*; import com.example.emos.wx.exception.EmosException; import com.example.emos.wx.service.UserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/user") @Api("用户模块Web接口") public class UserController { @Autowired private UserService userService; @Autowired private JwtUtil jwtUtil; @Autowired private RedisTemplate redisTemplate; @Value("${emos.jwt.cache-expire}") private int cacheExpire; // @Value("${trtc.appid}") // private Integer appid; // // @Value("${trtc.key}") // private String key; // // @Value("${trtc.expire}") // private Integer expire; @PostMapping("/register") @ApiOperation("注册用户") public R register(@Valid @RequestBody RegisterForm form){ int id=userService.registerUser(form.getRegisterCode(),form.getCode(),form.getNickname(),form.getPhoto()); String token=jwtUtil.createToken(id); Set<String> permsSet=userService.searchUserPermissions(id); saveCacheToken(token,id); return R.ok("用户注册成功").put("token",token).put("permission",permsSet); } @PostMapping("/login") @ApiOperation("登陆系统") public R login(@Valid @RequestBody LoginForm form){ int id=userService.login(form.getCode()); String token=jwtUtil.createToken(id); saveCacheToken(token,id); Set<String> permsSet = userService.searchUserPermissions(id); return R.ok("登陆成功").put("token",token).put("permission",permsSet); } // @GetMapping("/searchUserSummary") // @ApiOperation("查询用户摘要信息") // public R searchUserSummary(@RequestHeader("token") String token){ // int userId=jwtUtil.getUserId(token); // HashMap map=userService.searchUserSummary(userId); // return R.ok().put("result",map); // } // // @PostMapping("/searchUserGroupByDept") // @ApiOperation("查询员工列表,按照部门分组排列") // @RequiresPermissions(value = {"ROOT","EMPLOYEE:SELECT"},logical = Logical.OR) // public R searchUserGroupByDept(@Valid @RequestBody SearchUserGroupByDeptForm form){ // ArrayList<HashMap> list=userService.searchUserGroupByDept(form.getKeyword()); // return R.ok().put("result",list); // } // // @PostMapping("/searchMembers") // @ApiOperation("查询成员") // @RequiresPermissions(value = {"ROOT", "MEETING:INSERT", "MEETING:UPDATE"},logical = Logical.OR) // public R searchMembers(@Valid @RequestBody SearchMembersForm form){ // if(!JSONUtil.isJsonArray(form.getMembers())){ // throw new EmosException("members不是JSON数组"); // } // List param=JSONUtil.parseArray(form.getMembers()).toList(Integer.class); // ArrayList list=userService.searchMembers(param); // return R.ok().put("result",list); // } // // @PostMapping("/selectUserPhotoAndName") // @ApiOperation("查询用户姓名和头像") // @RequiresPermissions(value = {"WORKFLOW:APPROVAL"}) // public R selectUserPhotoAndName(@Valid @RequestBody SelectUserPhotoAndNameForm form){ // if(!JSONUtil.isJsonArray(form.getIds())){ // throw new EmosException("参数不是JSON数组"); // } // List<Integer> param=JSONUtil.parseArray(form.getIds()).toList(Integer.class); // List<HashMap> list=userService.selectUserPhotoAndName(param); // return R.ok().put("result",list); // } // // @GetMapping("/genUserSig") // @ApiOperation("生成用户签名") // public R genUserSig(@RequestHeader("token") String token){ // int id=jwtUtil.getUserId(token); // String email=userService.searchMemberEmail(id); // TLSSigAPIv2 api=new TLSSigAPIv2(appid,key); // String userSig=api.genUserSig(email,expire); // return R.ok().put("userSig",userSig).put("email",email); // } private void saveCacheToken(String token,int userId){ redisTemplate.opsForValue().set(token,userId+"",cacheExpire, TimeUnit.DAYS); } }
CheckinServiceImpl
package com.example.emos.wx.service.impl; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateRange; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; import com.example.emos.wx.config.SystemConstants; import com.example.emos.wx.db.dao.*; import com.example.emos.wx.db.pojo.TbCheckin; import com.example.emos.wx.db.pojo.TbFaceModel; import com.example.emos.wx.exception.EmosException; import com.example.emos.wx.service.CheckinService; //import com.example.emos.wx.task.EmailTask; import lombok.extern.slf4j.Slf4j; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.mail.SimpleMailMessage; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @Service @Scope("prototype") @Slf4j public class CheckinServiceImpl implements CheckinService { @Autowired private SystemConstants constants; @Autowired private TbHolidaysDao holidaysDao; @Autowired private TbWorkdayDao workdayDao; @Autowired private TbCheckinDao checkinDao; // @Autowired // private TbFaceModelDao faceModelDao; // // @Autowired // private TbCityDao cityDao; // // @Autowired // private TbUserDao userDao; // @Value("${emos.face.createFaceModelUrl}") // private String createFaceModelUrl; // // @Value("${emos.face.checkinUrl}") // private String checkinUrl; // // @Value("${emos.email.hr}") // private String hrEmail; // // @Value("${emos.code}") // private String code; // // @Autowired // private EmailTask emailTask; @Override public String validCanCheckIn(int userId, String date) { boolean bool_1 = holidaysDao.searchTodayIsHolidays() != null ? true : false; boolean bool_2 = workdayDao.searchTodayIsWorkday() != null ? true : false; String type = "工作日"; if (DateUtil.date().isWeekend()) { type = "节假日"; } if (bool_1) { type = "节假日"; } else if (bool_2) { type = "工作日"; } if (type.equals("节假日")) { return "节假日不需要考勤"; } else { DateTime now = DateUtil.date(); String start = DateUtil.today() + " " + constants.attendanceStartTime; String end = DateUtil.today() + " " + constants.attendanceEndTime; DateTime attendanceStart = DateUtil.parse(start); DateTime attendanceEnd = DateUtil.parse(end); if(now.isBefore(attendanceStart)){ return "没到上班考勤开始时间"; } else if(now.isAfter(attendanceEnd)){ return "超过了上班考勤结束时间"; }else { HashMap map=new HashMap(); map.put("userId",userId); map.put("date",date); map.put("start",start); map.put("end",end); boolean bool=checkinDao.haveCheckin(map)!=null?true:false; return bool?"今日已经考勤,不用重复考勤" : "可以考勤"; } } } // // @Override // public void checkin(HashMap param) { // Date d1=DateUtil.date(); // Date d2=DateUtil.parse(DateUtil.today()+" "+constants.attendanceTime); // Date d3=DateUtil.parse(DateUtil.today()+" "+constants.attendanceEndTime); // int status=1; // if(d1.compareTo(d2)<=0){ // status=1; // } // else if(d1.compareTo(d2)>0&&d1.compareTo(d3)<0){ // status=2; // } // else{ // throw new EmosException("超出考勤时间段,无法考勤"); // } // int userId= (Integer) param.get("userId"); // String faceModel=faceModelDao.searchFaceModel(userId); // if(faceModel==null){ // throw new EmosException("不存在人脸模型"); // } // else{ // String path=(String)param.get("path"); // HttpRequest request= HttpUtil.createPost(checkinUrl); // request.form("photo", FileUtil.file(path),"targetModel",faceModel); // request.form("code",code); // HttpResponse response=request.execute(); // if(response.getStatus()!=200){ // log.error("人脸识别服务异常"); // throw new EmosException("人脸识别服务异常"); // } // String body=response.body(); // if("无法识别出人脸".equals(body)||"照片中存在多张人脸".equals(body)){ // throw new EmosException(body); // } // else if("False".equals(body)){ // throw new EmosException("签到无效,非本人签到"); // } // else if("True".equals(body)){ // //查询疫情风险等级 // int risk=1; // String city= (String) param.get("city"); // String district= (String) param.get("district"); // String address= (String) param.get("address"); // String country= (String) param.get("country"); // String province= (String) param.get("province"); // if(!StrUtil.isBlank(city)&&!StrUtil.isBlank(district)){ // String code=cityDao.searchCode(city); // try{ // String url = "http://m." + code + ".bendibao.com/news/yqdengji/?qu=" + district; // Document document=Jsoup.connect(url).get(); // Elements elements=document.getElementsByClass("list-content"); // if(elements.size()>0){ // Element element=elements.get(0); // String result=element.select("p:last-child").text(); result="高风险"; // if("高风险".equals(result)){ // risk=3; // //发送告警邮件 // HashMap<String,String> map=userDao.searchNameAndDept(userId); // String name = map.get("name"); // String deptName = map.get("dept_name"); // deptName = deptName != null ? deptName : ""; // SimpleMailMessage message=new SimpleMailMessage(); // message.setTo(hrEmail); // message.setSubject("员工" + name + "身处高风险疫情地区警告"); // message.setText(deptName + "员工" + name + "," + DateUtil.format(new Date(), "yyyy年MM月dd日") + "处于" + address + ",属于新冠疫情高风险地区,请及时与该员工联系,核实情况!"); // emailTask.sendAsync(message); // } // else if("中风险".equals(result)){ // risk=2; // } // } // }catch (Exception e){ // log.error("执行异常",e); // throw new EmosException("获取风险等级失败"); // } // } // //保存签到记录 // TbCheckin entity=new TbCheckin(); // entity.setUserId(userId); // entity.setAddress(address); // entity.setCountry(country); // entity.setProvince(province); // entity.setCity(city); // entity.setDistrict(district); // entity.setStatus((byte) status); // entity.setRisk(risk); // entity.setDate(DateUtil.today()); // entity.setCreateTime(d1); // checkinDao.insert(entity); // } // } // } // // @Override // public void createFaceModel(int userId, String path) { // HttpRequest request=HttpUtil.createPost(createFaceModelUrl); // request.form("photo",FileUtil.file(path)); // request.form("code",code); // HttpResponse response=request.execute(); // String body=response.body(); // if("无法识别出人脸".equals(body)||"照片中存在多张人脸".equals(body)){ // throw new EmosException(body); // } // else{ // TbFaceModel entity=new TbFaceModel(); // entity.setUserId(userId); // entity.setFaceModel(body); // faceModelDao.insert(entity); // } // } // // @Override // public HashMap searchTodayCheckin(int userId) { // HashMap map=checkinDao.searchTodayCheckin(userId); // return map; // } // // @Override // public long searchCheckinDays(int userId) { // long days=checkinDao.searchCheckinDays(userId); // return days; // } // // @Override // public ArrayList<HashMap> searchWeekCheckin(HashMap param) { // ArrayList<HashMap> checkinList=checkinDao.searchWeekCheckin(param); // ArrayList holidaysList=holidaysDao.searchHolidaysInRange(param); // ArrayList workdayList=workdayDao.searchWorkdayInRange(param); // DateTime startDate=DateUtil.parseDate(param.get("startDate").toString()); // DateTime endDate=DateUtil.parseDate(param.get("endDate").toString()); // DateRange range=DateUtil.range(startDate,endDate,DateField.DAY_OF_MONTH); // ArrayList<HashMap> list=new ArrayList<>(); // range.forEach(one->{ // String date=one.toString("yyyy-MM-dd"); // String type="工作日"; // if(one.isWeekend()){ // type="节假日"; // } // if(holidaysList!=null&&holidaysList.contains(date)){ // type="节假日"; // } // else if(workdayList!=null&&workdayList.contains(date)){ // type="工作日"; // } // String status=""; // if(type.equals("工作日")&&DateUtil.compare(one,DateUtil.date())<=0){ // status="缺勤"; // boolean flag=false; // for (HashMap<String,String> map:checkinList){ // if(map.containsValue(date)){ // status=map.get("status"); // flag=true; // break; // } // } // DateTime endTime=DateUtil.parse(DateUtil.today()+" "+constants.attendanceEndTime); // String today=DateUtil.today(); // if(date.equals(today)&&DateUtil.date().isBefore(endTime)&&flag==false){ // status=""; // } // } // HashMap map=new HashMap(); // map.put("date",date); // map.put("status",status); // map.put("type",type); // map.put("day",one.dayOfWeekEnum().toChinese("周")); // list.add(map); // }); // return list; // } // // @Override // public ArrayList<HashMap> searchMonthCheckin(HashMap param) { // return this.searchWeekCheckin(param); // } }
UserServiceImpl
package com.example.emos.wx.service.impl; import cn.hutool.core.util.IdUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.example.emos.wx.db.dao.TbDeptDao; import com.example.emos.wx.db.dao.TbUserDao; //import com.example.emos.wx.db.pojo.MessageEntity; import com.example.emos.wx.db.pojo.TbUser; import com.example.emos.wx.exception.EmosException; import com.example.emos.wx.service.UserService; //import com.example.emos.wx.task.MessageTask; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import java.util.*; @Service @Slf4j @Scope("prototype") public class UserServiceImpl implements UserService { @Value("${wx.app-id}") private String appId; @Value("${wx.app-secret}") private String appSecret; @Autowired private TbUserDao userDao; // @Autowired // private TbDeptDao deptDao; // // @Autowired // private MessageTask messageTask; private String getOpenId(String code){ String url="https://api.weixin.qq.com/sns/jscode2session"; HashMap map=new HashMap(); map.put("appid", appId); map.put("secret", appSecret); map.put("js_code", code); map.put("grant_type", "authorization_code"); String response=HttpUtil.post(url,map); JSONObject json=JSONUtil.parseObj(response); String openId=json.getStr("openid"); if(openId==null||openId.length()==0){ throw new RuntimeException("临时登陆凭证错误"); } return openId; } @Override public int registerUser(String registerCode, String code, String nickname, String photo) { if(registerCode.equals("000000")){ boolean bool=userDao.haveRootUser(); if(!bool){ String openId=getOpenId(code); HashMap param=new HashMap(); param.put("openId", openId); param.put("nickname", nickname); param.put("photo", photo); param.put("role", "[0]"); param.put("status", 1); param.put("createTime", new Date()); param.put("root", true); userDao.insert(param); int id=userDao.searchIdByOpenId(openId); // MessageEntity entity=new MessageEntity(); // entity.setSenderId(0); // entity.setSenderName("系统消息"); // entity.setUuid(IdUtil.simpleUUID()); // entity.setMsg("欢迎您注册成为超级管理员,请及时更新你的员工个人信息。"); // entity.setSendTime(new Date()); // messageTask.sendAsync(id+"",entity); return id; } else{ throw new EmosException("无法绑定超级管理员账号"); } } else{ } return 0; } @Override public Set<String> searchUserPermissions(int userId) { Set<String> permissions=userDao.searchUserPermissions(userId); return permissions; } @Override public Integer login(String code) { String openId=getOpenId(code); Integer id=userDao.searchIdByOpenId(openId); if(id==null){ throw new EmosException("帐户不存在"); } return id; } @Override public TbUser searchById(int userId) { TbUser user=userDao.searchById(userId); return user; } // @Override // public String searchUserHiredate(int userId) { // String hiredate=userDao.searchUserHiredate(userId); // return hiredate; // } // // @Override // public HashMap searchUserSummary(int userId) { // HashMap map=userDao.searchUserSummary(userId); // return map; // } // // @Override // public ArrayList<HashMap> searchUserGroupByDept(String keyword) { // ArrayList<HashMap> list_1=deptDao.searchDeptMembers(keyword); // ArrayList<HashMap> list_2=userDao.searchUserGroupByDept(keyword); // for(HashMap map_1:list_1){ // long deptId=(Long)map_1.get("id"); // ArrayList members=new ArrayList(); // for(HashMap map_2:list_2){ // long id=(Long) map_2.get("deptId"); // if(deptId==id){ // members.add(map_2); // } // } // map_1.put("members",members); // } // return list_1; // } // // @Override // public ArrayList<HashMap> searchMembers(List param) { // ArrayList<HashMap> list=userDao.searchMembers(param); // return list; // } // // @Override // public List<HashMap> selectUserPhotoAndName(List param) { // List<HashMap> list=userDao.selectUserPhotoAndName(param); // return list; // } // // @Override // public String searchMemberEmail(int id) { // String email=userDao.searchMemberEmail(id); // return email; // } }
CheckinService
package com.example.emos.wx.service; import java.util.ArrayList; import java.util.HashMap; public interface CheckinService { public String validCanCheckIn(int userId,String date); // public void checkin(HashMap param); // public void createFaceModel(int userId,String path); // // public HashMap searchTodayCheckin(int userId); // // public long searchCheckinDays(int userId); // // public ArrayList<HashMap> searchWeekCheckin(HashMap param); // // public ArrayList<HashMap> searchMonthCheckin(HashMap param); }
UserService
package com.example.emos.wx.service; import com.example.emos.wx.db.pojo.TbUser; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; public interface UserService { public int registerUser(String registerCode,String code,String nickname,String photo); public Set<String> searchUserPermissions(int userId); public Integer login(String code); public TbUser searchById(int userId); // public String searchUserHiredate(int userId); // // public HashMap searchUserSummary(int userId); // // public ArrayList<HashMap> searchUserGroupByDept(String keyword); // // public ArrayList<HashMap> searchMembers(List param); // // public List<HashMap> selectUserPhotoAndName(List param); // // public String searchMemberEmail(int id); }
EmosWxApiApplication
package com.example.emos.wx; import cn.hutool.core.util.StrUtil; import com.example.emos.wx.config.SystemConstants; import com.example.emos.wx.db.dao.SysConfigDao; import com.example.emos.wx.db.pojo.SysConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.scheduling.annotation.EnableAsync; import javax.annotation.PostConstruct; import java.io.File; import java.lang.reflect.Field; import java.util.List; @SpringBootApplication @ServletComponentScan @Slf4j @EnableAsync public class EmosWxApiApplication { @Autowired private SysConfigDao sysConfigDao; @Autowired private SystemConstants constants; // @Value("${emos.image-folder}") // private String imageFolder; public static void main(String[] args) { SpringApplication.run(EmosWxApiApplication.class, args); } @PostConstruct public void init(){ List<SysConfig> list=sysConfigDao.selectAllParam(); list.forEach(one->{ String key=one.getParamKey(); key= StrUtil.toCamelCase(key); String value=one.getParamValue(); try{ Field field=constants.getClass().getDeclaredField(key); field.set(constants,value); }catch (Exception e){ log.error("执行异常",e); } }); // new File(imageFolder).mkdirs(); //生成测试数据 } }
TbUserDao.xml
<?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.example.emos.wx.db.dao.TbUserDao"> <select id="haveRootUser" resultType="boolean"> SELECT IF(COUNT(*),TRUE,FALSE) FROM tb_user WHERE root=1; </select> <select id="searchIdByOpenId" parameterType="String" resultType="Integer"> SELECT id FROM tb_user WHERE open_id=#{openId} AND status = 1 </select> <select id="searchUserPermissions" parameterType="int" resultType="String"> SELECT DISTINCT p.permission_name FROM tb_user u JOIN tb_role r ON JSON_CONTAINS(u.role, CAST(r.id AS CHAR)) JOIN tb_permission p ON JSON_CONTAINS(r.permissions, CAST(p.id AS CHAR)) WHERE u.id=#{userId} AND u.status=1; </select> <select id="searchById" parameterType="int" resultType="com.example.emos.wx.db.pojo.TbUser"> SELECT id, open_id, nickname, photo, name, sex, tel, role, root, dept_id, status, create_time FROM tb_user WHERE id=#{userId} AND status=1 </select> <!-- <select id="searchNameAndDept" parameterType="int" resultType="HashMap">--> <!-- SELECT u.name, d.dept_name--> <!-- FROM tb_user u LEFT JOIN tb_dept d ON u.dept_id=d.id--> <!-- WHERE u.id = #{userId} AND u.status = 1--> <!-- </select>--> <!-- <select id="searchUserHiredate" parameterType="int" resultType="String">--> <!-- SELECT hiredate FROM tb_user--> <!-- WHERE id=#{userId} AND status=1--> <!-- </select>--> <!-- <select id="searchUserSummary" parameterType="int" resultType="HashMap">--> <!-- SELECT u.name, u.photo, d.dept_name AS deptName--> <!-- FROM tb_user u LEFT JOIN tb_dept d ON u.dept_id=d.id--> <!-- WHERE u.id=#{userId} AND u.status=1--> <!-- </select>--> <!-- <select id="searchUserGroupByDept" parameterType="String" resultType="HashMap">--> <!-- SELECT--> <!-- d.id AS deptId,--> <!-- d.dept_name AS deptName,--> <!-- u.id AS userId,--> <!-- u.name--> <!-- FROM tb_dept d JOIN tb_user u ON u.dept_id=d.id--> <!-- WHERE u.status=1--> <!-- <if test="keyword!=null">--> <!-- AND u.name LIKE '%${keyword}%'--> <!-- </if>--> <!-- ORDER BY d.id, u.id;--> <!-- </select>--> <!-- <select id="searchMembers" parameterType="list" resultType="HashMap">--> <!-- SELECT id,name,photo--> <!-- FROM tb_user--> <!-- WHERE status = 1--> <!-- AND id IN--> <!-- <foreach collection="list" item="one" separator="," open="(" close=")">--> <!-- #{one}--> <!-- </foreach>--> <!-- </select>--> <!-- <select id="searchUserInfo" parameterType="int" resultType="HashMap">--> <!-- SELECT--> <!-- u.open_id AS openId,--> <!-- u.nickname,--> <!-- u.name,--> <!-- u.photo,--> <!-- u.sex,--> <!-- u.tel,--> <!-- u.email,--> <!-- d.dept_name AS dept,--> <!-- u.hiredate,--> <!-- CASE u.status--> <!-- WHEN 1 THEN "在职"--> <!-- WHEN 2 THEN "离职"--> <!-- END AS status,--> <!-- ( SELECT GROUP_CONCAT( role_name separator "," ) FROM tb_role WHERE JSON_CONTAINS ( u.role, CONVERT ( id, CHAR ) ) ) AS roles--> <!-- FROM tb_user u--> <!-- LEFT JOIN tb_dept d ON u.dept_id = d.id--> <!-- WHERE u.id = #{userId} AND u.status = 1--> <!-- </select>--> <!-- <select id="searchDeptManagerId" parameterType="int" resultType="int">--> <!-- SELECT--> <!-- u2.id--> <!-- FROM tb_user u1 JOIN tb_user u2 ON u1.dept_id=u2.dept_id--> <!-- JOIN tb_role r ON JSON_CONTAINS(u2.role, CAST(r.id AS CHAR))--> <!-- WHERE u1.id=#{id} AND r.id=2 AND u1.status = 1 AND u2.status = 1--> <!-- </select>--> <!-- <select id="searchGmId" resultType="int">--> <!-- SELECT--> <!-- u.id--> <!-- FROM tb_user u--> <!-- JOIN tb_role r ON JSON_CONTAINS(u.role, CAST(r.id AS CHAR))--> <!-- WHERE r.id=1 AND u.status = 1--> <!-- </select>--> <!-- <select id="selectUserPhotoAndName" parameterType="list" resultType="HashMap">--> <!-- SELECT--> <!-- id,name,photo--> <!-- FROM tb_user--> <!-- WHERE status = 1 AND id IN--> <!-- <foreach collection="list" open="(" close=")" item="one" separator=",">--> <!-- #{one}--> <!-- </foreach>--> <!-- </select>--> <!-- <select id="searchMemberEmail" parameterType="int" resultType="String">--> <!-- SELECT email FROM tb_user WHERE id=#{id} AND status = 1--> <!-- </select>--> <insert id="insert" parameterType="HashMap"> INSERT INTO tb_user SET <if test="openId!=null"> open_id = #{openId}, </if> <if test="nickname!=null"> nickname = #{nickname}, </if> <if test="photo!=null"> photo = #{photo}, </if> <if test="name!=null"> name = #{name}, </if> <if test="sex!=null"> sex = #{sex}, </if> <if test="tel!=null"> tel = #{tel}, </if> <if test="email!=null"> email=#{email}, </if> <if test="hiredate!=null"> hiredate = #{hiredate}, </if> role = #{role}, root = #{root}, <if test="deptName!=null"> dept_id = ( SELECT id FROM tb_dept WHERE dept_name = #{deptName} ), </if> status = #{status}, create_time = #{createTime} </insert> </mapper>
遇到的问题和bug
实现注册超级管理员的功能后,在注册时出现以下报错
并且数据库无注册数据
解决思路: 查看前端代码中main.js的路径是否填写正确,格式应为:本地ip+端口号
本地ip查找方法:打开命令行窗口,输入"ipconfig"即可查看
明后两天学习计划
学习第七第八章内容
学习进度和反思
- 目前看完六章学习视频
- 最近看视频的速度变快了,可是收获感却没有多多少,很多时候老师讲老师的,自己听不懂,只是复制源码然后调试,看见程序跑起来就算结束。反思下来,还是基础知识过于匮乏,学完这个项目就得恶补一波
本文含有隐藏内容,请 开通VIP 后查看