宠物之家项目 1.三方登录(微信) 步骤梳理 1.向后端发送前端请求,后端接收授权码,重定向扫码页面 //后端获取授权码 重定向到微信登录二维码界面 @GetMapping("/jump") public String getWechat(){ String codeUrl = wechatProperties.getAuthorizationCodeUrl(); String state = UUID.randomUUID().toString(); codeUrl = String.format(codeUrl, wechatProperties.getAppId(), wechatProperties.getRedirectUri(),state); return "redirect:" codeUrl; } 2.获取code String tokenUrl = wechatProperties.getTokenUrl(); tokenUrl=String.format(tokenUrl,wechatProperties.getAppId(), wechatProperties.getAppSecrect(), code); //2.1 发送微信请求 String result = HttpUtil.sendPost(tokenUrl, null); System.out.println(result); WechartTokenDto wechartTokenDto = JSONObject.parseObject(result, WechartTokenDto.class); System.out.println(wechartTokenDto); 3.根据code换token String userInfoUrl = wechatProperties.getUserinfoUrl(); //"https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s" userInfoUrl = String.format(userInfoUrl, wechartTokenDto.getAccess_token(), wechartTokenDto.getOpenid()); String userinfoResult = HttpUtil.sendPost(userInfoUrl, null); WechatUserInfoDto wechatUserInfoDto = JSONObject.parseObject(userinfoResult, WechatUserInfoDto.class); 4.用token获取用户信息 6.存在页看userId是否存在跳转绑定页面 WechatUser wechatUser = wechatUserList.get(0); Long userId = wechatUser.getUserId(); //如果是空的 if(userId==null){ //跳转到绑定页面 return "redirect:http://127.0.0.1:6002/binder.html?id=" wechatUser.getId(); }else{ LoginInfo login = loginInfoMapper.selectByPrimaryKey(userId); String token = UUID.randomUUID().toString(); redisTemplate.opsForValue().set(token, JSONObject.toJSONString(login), 30, TimeUnit.MINUTES); //将结果返回到前端 用map HashMap<String, Object> map = new HashMap<>(); &nbs; map.put("token", token); map.put("userInfo", login); //跳转到首页 String redirectUrl = "redirect:http://localhost:6002/index.html?userInfo=%s&token=%s"; redirectUrl = String.format(redirectUrl, login.getUsername(), token); redirectUrl = StrUtil.cleanBlank(redirectUrl); return redirectUrl; } } } return "redirect:http://127.0.0.1:6002/index.html"; 5.判断是否存在数据库,不存在跳转绑定页面 //4.根据openid看wxuser表是否存在 Example example = new Example(WechatUser.class); example.and().andEqualTo("openid",wechatUserInfoDto.getOpenid()); List<WechatUser> wechatUserList = wechatUserMapper.selectByExample(example); //看是否第一次登录 if(CollectionUtils.isEmpty(wechatUserList)){ //如果为空 说明第一次登录 先把数据信息存入表 WechatUser wechatUser = new WechatUser(); wechatUser.setHeadimgurl(wechatUserInfoDto.getHeadimgurl()); wechatUser.setOpenid(wechatUserInfoDto.getOpenid()); wechatUser.setNickname(wechatUserInfoDto.getNickname()); wechatUser.setUnionid(wechatUserInfoDto.getUnionid()); wechatUserMapper.insert(wechatUser); //跳转到绑定页面 return "redirect:http://127.0.0.1:6002/binder.html?id="+wechatUser.getId(); 微信参数实体类 @Data @Component @ConfigurationProperties("pethome.wechart") public class WechatProperties { private String authorizationCodeUrl; private String userinfoUrl; private String refreshTokenUrl; private String appId; private String appSecrect; private String redirectUri; private String tokenUrl; } yml配置 pethome: wechart: #获取授权码URL authorization-code-url: "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect" #获取Token的URL token-url: "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" #获取用户信息 URL userinfo-url: "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s" #刷新Token的 URL refresh-token-url: "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s" # 应用ID app-id: "wxd853562a0548a7d0" # 应用秘钥 app-secrect: "4a5d5615f93f24bdba2ba8534642dbb6" # 授权码回调接口,对应我们平台的controller redirect-uri: "http://bugtracker.itsource.cn/wechat/callback" 2.三方支付(支付宝) 前置条件 1.拉起支付页面工具类 public JSONResult createPayUrl(AlipayBean alipayBean, Long userId) { System.out.println("发起支付,入参:" + alipayBean.toString()); try { // 1. 设置参数 Factory.setOptions(alipayInfo.getOptions()); // 2. 发起API调用 AlipayTradePagePayResponse response = Factory.Payment.Page() .pay(alipayBean.getSubject(), alipayBean.getOutTradeNo(), alipayBean.getTotalAmount(), alipayInfo.getReturnUrl()); // 3. 处理响应或异常 if (ResponseChecker.success(response)) { System.out.println("发起支付调用成功,响应结果:" + response.getBody()); return JSONResult.success(response.getBody()); } else { return JSONResult.error("发起支付调用失败,响应结果:" + response.getBody()); } } catch (Exception e) { return JSONResult.error("发起支付失败:" + e.getLocalizedMessage()); } }
2.订单页面参数设置 @Data @ToString public class AlipayBean { /** 订单号 */ private String outTradeNo; /** 订单支付金额,单位:元 */ private String totalAmount; /** 订单标题 */ private String subject; } 3.支付宝返回的表单,yml里面的参数实体类 @Component @ConfigurationProperties(prefix = "alibabapay.params") @Data public class AlipayParams {
private String appId; private String protocol; private String gatewayHost; private String alibabaPublicKey; private String merchantPrivateKey; private String signType; private String notifyUrl; private String returnUrl;
public Config getOptions() { Config config = new Config(); config.protocol = protocol; config.gatewayHost = gatewayHost; config.signType = signType; config.appId = appId; //应用私钥 config.merchantPrivateKey = merchantPrivateKey; //支付宝公钥 config.alipayPublicKey = alibabaPublicKey; //可设置异步通知接收服务地址(可选) config.notifyUrl = notifyUrl; return config; } } 4.yml配置 # 关于支付的相关配置参数 alibabapay: params: #应用ID app-id: "2021000120615953" #协议 protocol: "https" #网关地址 gateway-host: "openapi.alipaydev.com" #支付宝公钥 alibaba-public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtLTf1fyuhjU0YpMwzkSbs/jB9UoWBiQgw4tkCPSeBbyj6wAPUqs2Rar4Z2R+06SRL0aarm6xzP+p2nGgHwYRNmLjbM8qntlef6/36xN/px7YEXwT9vdPAP77NbE5+UsFTzhyasZRgeWqCdSzL3Cq0ISGXOE+4kxChIwvctcvCLyWJ9529ICijIQ81MTyAVMz70x5/ZPSHKKz5CHDe7BSc7PpknpumewDLrqv+Lsol6vC0VfO8ilqSFha9DK2kzLN/Mjtix1P9m+M4HArEoivBhxAXvIlHQypkHmCbtahAKf5c17Y79DZxUGpBH/LOIf9x1TbtNBvm9XZrXd62k5BqQIDAQAB" #商户私钥 merchant-private-key: "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCLHcjkKIu1XHQjH0Uenie6cQO5Zamb/sjaTVhL1jYohvprTjOXmif3CrRng9rWFamfZxaXzGvc87RPW2Pv8kt9HVxlyckKb5l6By2APOw9aL3vpwUBvinCNCZGAgPgKacZMfJL78TLTpTOWfKRR8nZ2WmfXcbGmMWSXb/3MQN+kgJ10juJgB4Tkp8UUGhLqGwRwRfJzpX5GSBiSoDhvhSGeYyGF461g/kGKQU33qCOVwZpxnRHa2xLBkUFoSBH2LW2d5r+auaE9uOERni5J1fAxdrjVV2Hu32PSTK6VcSoV8lxh1P7WUWm6Fdg2q2NXE6Jlo9/8ga81zqi5vv6HU1bAgMBAAECggEAdi8rh4lahwywLVZXZhd+MMnqHArd+ISPJcYniOXGxM9G1vpsohJ4eUtCz94Yf1+P5rexXexwhhkTyYcec64nq3bSFDdE7/S3Mg/++77GA7WEBqChhEWFPFMJYNg9aqZ4KtNfwFtFmGJ90IBhrkKKnOQy8wy73ePTlPDIMLwW9+LV3DNoi5nXuIcz3QONDeFmr61R2OQ+xB+N02Tyt7FcKJ19u5u1yfcrP1q5DL3l6ieMdRtBBfPI0Drg0Uc9UBtMra/izlrdY2zXb1hHnoIKyta2ETwAjosCkog969Bx15/G/YneAyZZDNO/OXCMo5z5kn8n2+3ltOMHHSIfQxkvgQKBgQDevdMKTTgTSTwGFJwmOjPJQ5rmDECPwcRa0wLfCRQ8RnXpXE9sLPE9ghyVHKT0JF+OPSaw1/wTP7r0a6Dffux87Y/zp5gvitAn3rZng5iSK4q41EhqnGmUE/rGG8FvJHSTJf/geCwTca5fh7T/rzLHKoJ/JhECl99+rfIbJTQjawKBgQCf427nFT4KOkvMt2z/WnYH+bOkIRoLjFQxTjuFPl8eQoIJH8UTTA8FWT21ZFa9PhOKzXI2+BWxH7qxV+r2Ilxflm8u149wAoJsSKpatbAhD7J+Z+ls6762+ESVGarDy0dA0+JnAEczoL4+fKd7Ml9R//gm9Y9r04+PqvpNVvDp0QKBgF7t8fKzBFIb5SwGPqKALa/6Uxr2X9Gk2GWJBvE9clVaBkjFocfNw6bePAZE5fxzQBJj94hpFLKzd59R+4clFe8MZEyIwfCJLbvATGcDi9PIIOAzAQYG0Wxds4QZMjCHDfPkvw/Qx6Al1BY8xSQva+m8MU+1ToyXY5Ye1k9BZN4vAoGALLbWFRoDt6iF+kJx4RfTWneinYwEVKZyBTfzvVesEjJXW2XfH35t1PkYINpmx5XMsUyzXFwU9OwCsgX8V8lUPAc+IMN4AcMx5kaMHcIh950ENgWpaiSjuVfFFk2PTCJVUvPupQ+W2gFiMud5jyKPNcd4Bq015tnLlEokpexig4ECgYBV2LW2qD2NaHAxDHVh7R7LrGm3DZsB7848Lwrfx9dUrK8gsmmhwud7D62RkFpPigqhvKeYBgBxbyb735FZ4erwYve5LwuLnwImkP774CqxNdKVWBPnHfFwrroJ2UuCGiwDFG5n7wDuK9XNiFc+IkABZR9FAYl4FFi2DNGK0B0Z0w==" #签名方式 sign-type: "RSA2" #异步回调,用户不可见,用户完成支付之后,支付宝会调用这个地址,告知我们支付结果 notify-url: "http://hdcwzp.natappfree.cc/payPro/alipay/notify" #同步回调,用户可见,用户支付完成之后,页面跳转到这里这个地址,是我们系统的一个地址 return-url: "http://hdcwzp.natappfree.cc/payPro/alipay/return" 步骤 1.用户点击提交订单,后台校验参数 2.入参校验,通过订单id查看宠物id是否存在,再查看用户id是否存在 3.验证通过后,把订单入库,订单库存-1 //1.2根据宠物id拿到宠物信息,订单信息存入orderAdopt表 Pet pet = petMapper.selectByPrimaryKey(petId); Integer miaoshaId = pet.getMiaoshashop(); if(miaoshaId==1){ return JSONResult.error("此宠物为秒杀商品,请需要秒杀的时候再来"); } OrderAdopt orderinfo = new OrderAdopt();//创建订单实例,给orderAdopt表赋值 orderinfo.setCreateTime(new Date());//创建时间 orderinfo.setState(0);//修改状态 状态(0:待支付;1:支付成功;2:支付失败) orderinfo.setPrice(pet.getSaleprice());//商品售价 String orderSn = MyUtil.getOrderSn(); orderinfo.setOrderSn(orderSn);//订单编号 ~随机数 orderinfo.setUserinfoId(currentId);//用户id // orderinfo.setLastPayTime(new Date());//支付时间 orderinfo.setShopId(pet.getShopId());//商品id orderinfo.setPetId(pet.getId());//宠物id orderinfo.setPaySn("支付中");//支付说明 UserAddress userAddress = orderAdopt.getUserAddress();//获取用户的收获地址对象 orderinfo.setAddressId(userAddress.getId()); Date date = TimeUtil.addMin(1); orderinfo.setLastConfirmTime(date);//最后支付时间设置为30分钟 orderinfo.setDigest(pet.getName());//宠物名 orderAdoptMapper.insert(orderinfo); 4.再把收货地址信息入库 //1.4把收获地址存入t_order_address表; OrderAddress orderAddress = new OrderAddress(); orderAddress.setOrder_sn(orderSn);//订单号 orderAddress.setCreate_time(new Date());//创建时间 orderAddress.setPhone(userAddress.getPhone());//手机号 orderAddress.setAddress(userAddress.getAddress());//详细地址 orderAddress.setContacts(userAddress.getContacts());//联系人 orderAddress.setArea_code(userAddress.getAreaCode());//所在街道 orderAddress.setEmail(userAddress.getEmail());//邮箱 orderAddress.setFull_address(userAddress.getFullAddress());//全地址 orderAddress.setPhone_back(userAddress.getPhoneBack());//备用手机号 orderAddress.setPost_code(userAddress.getPostCode());//邮编 orderAddress.setTel(userAddress.getTel());//固定电话 orderAddressMapper.insert(orderAddress);//收货地址信息入库 4.通过quartz定时器,设置最后确认时间 Map map = new HashMap(); map.put("orderAdoptId",orderinfo.getId()); //超时订单关闭 QuartzUtils.addJob(scheduler,"超时关单",PrintTimeJob.class,map, QuartzJobInfo.setFireDate(date)); 5.拉起支付页面 //2.拉起订单支付页面
alipayParams.setNotifyUrl("http://hdcwzp.natappfree.cc/pay/alipay/notify"); alipayParams.setReturnUrl("http://hdcwzp.natappfree.cc/pay/alipay/return"); AlipayBean alipayBean = new AlipayBean();//支付页面显示的参数 alipayBean.setSubject("购买商品名:" + pet.getName() + ";需支付金额:"+orderinfo.getPrice().toString()); alipayBean.setTotalAmount(orderinfo.getPrice().toString());//宠物售价 alipayBean.setOutTradeNo(orderSn);//订单编号 ~随机数 return alipayService.createPayUrl(alipayBean,currentId);//拉起支付页面 6.回调接口 异步回调 处理回调结果,处理业务 一共会发7次请求,返回结果必须为success 业务步骤 1.通过支付宝返回的表单,进行验签操作,验证订单号,订单价格,订单名称 2.验证通过后,.修改状态 3.返回“success” 必须返回success这七个字符 同步回调 显示回调结果,不处理业务 进行验签操作 验证异步处理的状态,返回给用户展示 3.邮件发送(qq邮箱) 使用步骤 前置条件 到qq邮箱里开启授权码,到yml里配置密钥 mail: host: smtp.qq.com # 设置邮箱主机(服务商),这里使用QQ邮件服务器 username: 1160097325@qq.com # 设置用户名 password: fumwomjttocxbaee # 设置密码,该处的密码是QQ邮箱开启SMTP的授权码而非QQ密码 properties: mail: smtp: auth: true # 必须进行授权认证,它的目的就是阻止他人任意乱发邮件 starttls: #SMTP加密方式:连接到一个TLS保护连接 enable: true required: true 1.导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.4</version> </dependency> 2.注入对象 JavaMailSender 3.调用方法 SimpleMailMessage simpleMailMessage = new SimpleMailMessage(); //发送人 simpleMailMessage.setFrom(username); //发送的标题 simpleMailMessage.setSubject(subject); //发送的内容 simpleMailMessage.setText(context); //发送的收件人 simpleMailMessage.setTo(to); ———————————————— 4.短信发送(网建短信通) 使用步骤 1.导入依赖 <dependency> <groupId>commons-httpclient</groupId> <artifactId>commons-httpclient</artifactId> <version>3.1</version> </dependency> 2.网建短信通 进入网站查看Java API说明 https://www.smschinese.com.cn/Login.shtml 3.导入工具包,修改用户名和密钥可直接使用 @Slf4j public class HttpUtil { //发送post请求 public static String sendPost(String url, Map<String,String> params){ try { //创建http客户端 HttpClient client = new HttpClient(); //创建post请求,指定请求地址 PostMethod post = new PostMethod(url); //设置请求头 post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");//在头文件中设置转码 //添加参数:循环map,把map中的数据变成List Set<String> keys = params.keySet(); List<NameValuePair> paramList = new ArrayList<>(); for(String key: keys){ String value = params.get(key); paramList.add(new NameValuePair(key, value)); } //把list变成数组 NameValuePair[] data = paramList.toArray(new NameValuePair[]{}) ; post.setRequestBody(data); //执行请求 client.executeMethod(post); //获取结果 String result = new String(post.getResponseBodyAsString().getBytes("utf-8")); //打印返回消息状态 log.info("HttpUtil#sendPost: 网络请求结果{}",result); //释放连接 post.releaseConnection(); return result; } catch (IOException e) { e.printStackTrace(); } return null; } public static void sendMobileCode(String mobile, String text){ Map<String, String> param = new HashMap<>(); param.put("Uid",“”);//注册时填写的用户名 param.put("Key", "");//秘钥 param.put("smsMob", mobile); param.put("smsText", text); String result = HttpUtil.sendPost("http://utf8.api.smschinese.cn/", param); } } 5.Git工具 1.git的优势 1.可以实现多人合作 2.可以管理项目迭代 3.代码方便储存,电脑关闭也不会丢失 4.查看历史代码,代码还原 2.git的使用 1.先把代码从中央仓库clone到本地仓库 2.把代码add到缓冲区 3.commit到本地仓库 4.push到中央仓库 3.git在工作中的使用 1.把中央仓库代码clone到本地仓库 2.每天早上来pall拉一下最新的代码 3.每天晚上收工时commit&push提交一下代码 4.有冲突问题时事先协商解决 6.Redis(非关系型数据库) 概念:Redis是非关系型数据库,存储形式存在内存中,存储方式为(key,value). 优点 1.数据储存在内存中,读取速度快,性能高 2.储存方式多种多样 list String set zset hash 一般常见的分为此五种,还有很多数据结构 3.解决并发能力强 应用场景 1.消息订阅 2.缓存 3.队列 4.定时器 5.去重 6.设置有效期应用 7.Quarzt定时器框架的使用 概念 quarzt是一共完全由Java开发的定时器框架,轻量易用 缺点,无法处理高并发 适用场景一般分为 适用场景: 1.定时发邮件;
2.定时发报表;
3.定时关闭支付订单;
4.一系列定时操作都可以完成,功能强大; 组成部分分为 trigger触发器 jobDetail任务详情 job类实现job接口 jobDataMap:存放job参数 scheduler容器 使用步骤配置 动态配置job参数类 public static void addJob(Scheduler sched, String jobName, Class cls, Object params, String time) { try { //--------------------------创建 JobDetail 工作详情--------------------------------- JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME);// 任务名,任务组,任务执行类 //Job的数据 map JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("params", params); //根据传入的job的类,创建一个 JobDetail,并指定 JobKey,并把数据map设置给job JobDetail jobDetail = newJob(cls).withIdentity(jobKey).setJobData(jobDataMap).build();
//--------------------------创建 Trigger 触发器--------------------------------- //创建触发器的 key,相当于触发器的ID TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME); //创建触发器,设置触发器key,并关联一个 cronSchedule(基于表达式的时间规则) Trigger trigger = newTrigger().withIdentity(triggerKey).withSchedule(cronSchedule(time)).build();
//把工作详情和触发器设置到 schedule 调度容器中 sched.scheduleJob(jobDetail, trigger); //启动 if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { throw new RuntimeException(e); } } 关闭定时器任务 public static void removeJob(Scheduler sched, String jobName) { try { TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_GROUP_NAME); sched.pauseTrigger(triggerKey);// 停止触发器 sched.unscheduleJob(triggerKey);// 移除触发器 JobKey jobKey = new JobKey(jobName, JOB_GROUP_NAME); boolean b = sched.deleteJob(jobKey);// 删除任务 System.out.println(b); } catch (Exception e) { throw new RuntimeException(e); } } 配置将时间转weicorn表达式的类 //把时间变成时间表达式,在 fireDate 时间到的时候执行 public static String setFireDate(Date fireDate) { //this.fireDate = fireDate; String[] cronArr = new String[7]; for (int i = 0; i < cronArr.length; i++) { cronArr[i] = ""; } Calendar calendar = Calendar.getInstance(); calendar.setTime(fireDate); int second = calendar.get(Calendar.SECOND); int minute = calendar.get(Calendar.MINUTE); int hour = calendar.get(Calendar.HOUR_OF_DAY); int day = calendar.get(Calendar.DAY_OF_MONTH); int month = calendar.get(Calendar.MONTH) + 1; int year = calendar.get(Calendar.YEAR);
cronArr[0] = second + ""; cronArr[1] = minute + ""; cronArr[2] = hour + "";
cronArr[3] = day + ""; cronArr[4] = month + ""; cronArr[5] = "?"; cronArr[6] = year + "";
String cron = StringUtils.join(cronArr," ").trim(); System.out.println("cron==========" + cron); //this.setCronj(cron); return cron; } ———————————————— 版权声明:本文为CSDN博主「生活可真难啊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/m0_67574688/article/details/125251271 持久化的设置 yml配置 quartz: job-store-type: jdbc #持久化到数据库 properties: org: quartz: datasource: driver-class-name: com.mysql.jdbc.Driver jdbcUrl: jdbc:mysql://127.0.0.1:3306/pethome-quartz?useUnicode=true&characterEncoding=UTF-8 username: root password: 123456 scheduler: instancName: clusteredScheduler instanceId: AUTO jobStore: class: org.quartz.impl.jdbcjobstore.JobStoreTX driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate #StdJDBCDelegate说明支持集群 tablePrefix: QRTZ_ isClustered: true clusterCheckinInterval: 1000 useProperties: false threadPool: class: org.quartz.simpl.SimpleThreadPool threadCount: 20 threadPriority: 5 多数据源的配置类 @Configuration public class QuartzDataSourceConfig {
//主数据源 @Bean @Primary //主数据库,指向pethome @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource(){ return DataSourceBuilder.create().build(); } //为quartz创建一个自己数据源 @Bean @QuartzDataSource //quartz数据源 @ConfigurationProperties(prefix = "spring.quartz.properties.org.quartz.datasource") public DataSource quartzDataSource(){ return DataSourceBuilder.create().build(); } } 8.登录功能的实现 步骤 1.首先入参校验 //入参校验 if (!StrUtil.isNotEmpty(loginInfo.getUsername())) { return JSONResult.success("账号不能为空"); } if (!StrUtil.isNotEmpty(loginInfo.getPassword())) { return JSONResult.success("密码不能为空"); } 2.拿到账号,把账号拿去和数据库对比,看账号是否存在 3.账号存在,再比对密码是否正确 //校验账号 ,通过账号拿到密码 Example example = new Example(LoginInfo.class); example.and().andEqualTo("username", loginInfo.getUsername()); List<LoginInfo> infoList = loginInfoMapper.selectByExample(example); if(CollectionUtils.isEmpty(infoList)){ return JSONResult.error("账号错误之"); } LoginInfo login = infoList.get(0); //比对密码 存入redis String password = login.getPassword(); String infoPassword = loginInfo.getPassword(); if (!infoPassword.equals(password)) { return JSONResult.error("密码错误,请重新输入"); } 4.密码正确.把登录信息存入redis String token = UUID.randomUUID().toString(); redisTemplate.opsForValue().set(token, JSONObject.toJSONString(login), 30, TimeUnit.MINUTES); 5.把token和登录信息封装成map返回给前端 //返回结果给前端 用map HashMap<String, Object> map = new HashMap<>(); map.put("token", token); map.put("userInfo", login); return JSONResult.success(map); 8.扩展功能 1.接口防刷 2.权限管理 自定义注解+拦截器实现 知识点笔记积累 1.resultful风格:是一种面向资源的架构风格 优点 1.本身就是http,无状态,不用担心访问两次上下文. 2.透明性,暴露资源存在 3.充分利用http协议本身 2.swaggerUI风格 概念 是一个规范和完整的框架,用于生成可描述和可视化resultful风格的web服务 优点 1.接口文档自动生成 2.接口功能测试 3.线程里的start方法 可以用join方法解决抢占线程问题 4.注解@Autowired和@Resources的区别 @Autowired是由spring提供的 @Autowired是按类型自动注入 @Resource是由jdk提供的 @Resource是按名称自动注入 5.String.format 用来拼接占位符 定时器实现超时关单
/** * @author wujiangbo * @date 2022-06-12 15:13 */ public class PrintTimeJob implements Job {
@Autowired private OrderAdoptMapper orderAdoptMapper;
@Autowired private PetMapper petMapper; @Autowired private Scheduler scheduler;
@Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); //通过key获取value Map map = (HashMap)jobDataMap.get("params"); //在通过value的key获取value Long orderAdoptId = (Long)map.get("orderAdoptId"); System.out.println("订单id"+orderAdoptId); //查询当前订单,获取当前状态 OrderAdopt orderAdopt = orderAdoptMapper.selectByPrimaryKey(orderAdoptId); if(orderAdopt==null){ System.out.println("订单不存在"); } //判断当前状态是否为待支付 状态(0:待支付;1:支付成功;2:支付失败) if(orderAdopt.getState()==0){ //修改状态为支付失败 orderAdopt.setState(2); orderAdoptMapper.updateByPrimaryKeySelective(orderAdopt); System.out.println("订单修改完成"); //库存回库+1 Long petId = orderAdopt.getPetId();//获得宠物id Pet pet = petMapper.selectByPrimaryKey(petId);//通过宠物id获得宠物对象 pet.setCount(pet.getCount()+1); petMapper.updateByPrimaryKeySelective(pet); System.out.println("减库存成功"); } //关定时器 QuartzUtils.removeJob(scheduler,"超时关单"); System.out.println("关单"); } }
Map map = new HashMap(); map.put("orderAdoptId",orderinfo.getId()); //超时订单关闭 QuartzUtils.addJob(scheduler,"超时关单",PrintTimeJob.class,map, QuartzJobInfo.setFireDate(date)); 6.全局时间格式化的配置 package cn.itsource.pethome.config;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.boot.jackson.JsonComponent; import org.springframework.context.annotation.Bean; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.TimeZone;
/** * @description: 日期时间全局格式化 * @auth: wujiangbo * @date: 2022-03-09 17:38 */ @JsonComponent public class LocalDateTimeSerializerConfig {
@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}") private String pattern;
/** * Date 类型全局时间格式化 */ @Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilder() { return builder -> { TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");//获取时区 DateFormat df = new SimpleDateFormat(pattern);//设置格式化模板 df.setTimeZone(tz); builder.failOnEmptyBeans(false) .failOnUnknownProperties(false) .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .dateFormat(df); }; }
/** * LocalDate 类型全局时间格式化 */ @Bean public LocalDateTimeSerializer localDateTimeDeserializer() { return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)); }
@Bean public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer()); } } 7.糊涂依赖和小辣椒依赖 <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.8</version> </dependency>
<!--糊涂工具包--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.21</version> </dependency>