diff --git a/navigate-8432/pom.xml b/navigate-8432/pom.xml new file mode 100644 index 0000000..a381a9a --- /dev/null +++ b/navigate-8432/pom.xml @@ -0,0 +1,102 @@ + + + 4.0.0 + + com.ivmiku.tutorial + first-tutorial + 1.0-SNAPSHOT + + + navigate-8432 + + + 21 + 21 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + com.mysql + mysql-connector-j + runtime + + + org.projectlombok + lombok + provided + + + + cn.dev33 + sa-token-spring-boot3-starter + + + + com.alibaba.fastjson2 + fastjson2 + + + + cn.dev33 + sa-token-redis-jackson + 1.38.0 + + + org.apache.commons + commons-pool2 + + + + org.apache.dubbo + dubbo-spring-boot-starter + + + + org.apache.dubbo + dubbo-registry-nacos + + + org.springframework.cloud + spring-cloud-starter-loadbalancer + + + com.alibaba.cloud + spring-cloud-starter-alibaba-sentinel + + + com.ivmiku.tutorial + commons + 1.0-SNAPSHOT + + + + cn.hutool + hutool-http + 5.8.29 + + + com.tencentcloudapi + tencentcloud-sdk-java-ocr + 3.1.1076 + + + \ No newline at end of file diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/Main8432.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/Main8432.java new file mode 100644 index 0000000..9401c6a --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/Main8432.java @@ -0,0 +1,13 @@ +package com.ivmiku.tutorial; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan("com.ivmiku.tutorial.mapper") +public class Main8432 { + public static void main(String[] args) { + SpringApplication.run(Main8432.class, args); + } +} \ No newline at end of file diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/NavigateController.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/NavigateController.java new file mode 100644 index 0000000..927d070 --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/controller/NavigateController.java @@ -0,0 +1,62 @@ +package com.ivmiku.tutorial.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.stp.StpUtil; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.entity.RouteStep; +import com.ivmiku.tutorial.response.Result; +import com.ivmiku.tutorial.service.NavigateService; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@RestController +@RequestMapping("/navigate") +@SaCheckLogin +public class NavigateController { + @Resource + private NavigateService navigateService; + + private static final ConcurrentHashMap> STEPS_MAP = new ConcurrentHashMap<>(); + + @GetMapping("/route") + public Object getRoute(@RequestParam(defaultValue = "") String origin, + @RequestParam(defaultValue = "") String destination, + @RequestParam(defaultValue = "-1") int step) { + String userId = (String) StpUtil.getLoginId(); + if (!origin.isEmpty() && !destination.isEmpty()) { + Map route = navigateService.getRoute(origin, destination); + List stepsList = (List) route.get("steps"); + STEPS_MAP.put(userId, stepsList); + Map map = new HashMap<>(); + map.put("total", stepsList.size()); + map.put("distance", Integer.parseInt((String) route.get("distance"))); + map.put("duration", Integer.parseInt((String) route.get("duration"))); + map.put("step", stepsList.getFirst()); + return JSON.toJSON(Result.ok(map)); + } else if (step >0) { + if (!STEPS_MAP.containsKey(userId)) { + return JSON.toJSON(Result.error("请先获取路线!")); + } + Map map = new HashMap<>(); + map.put("step", STEPS_MAP.get(userId).get(step-1)); + return JSON.toJSON(Result.ok(map)); + } + return JSON.toJSON(Result.error("非法的请求参数")); + } + + @PostMapping("/ticket") + public Object scanTicket(@RequestPart MultipartFile file) throws IOException { + BufferedImage image = ImageIO.read(file.getInputStream()); + Map map = navigateService.scanTicket(image); + return JSON.toJSON(Result.ok(map)); + } +} diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/RouteStep.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/RouteStep.java new file mode 100644 index 0000000..b42e3bc --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/entity/RouteStep.java @@ -0,0 +1,16 @@ +package com.ivmiku.tutorial.entity; + +import lombok.Data; + +@Data +public class RouteStep { + private String instruction; + private String orientation; + private String road; + private Integer distance; + private Integer duration; + private String polyline; + private String action; + private String assistant_action; + private Integer walk_type; +} diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/service/NavigateService.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/NavigateService.java new file mode 100644 index 0000000..32ba49d --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/service/NavigateService.java @@ -0,0 +1,84 @@ +package com.ivmiku.tutorial.service; + +import cn.hutool.core.img.ImgUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.ivmiku.tutorial.entity.RouteStep; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.exception.TencentCloudSDKException; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import com.tencentcloudapi.ocr.v20181119.OcrClient; +import com.tencentcloudapi.ocr.v20181119.models.*; +import org.springframework.stereotype.Service; + +import java.awt.image.BufferedImage; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class NavigateService { + private final String key = "d3aa1b75aff468a5ca5384d2b4b6bfef"; + private final String secretId = "AKID09INNYxYEFFJH3g9VhljVF3qbDiFdx50"; + private final String secretKey = "KajjcNyNaaUCqQroqpzNoMtTHNj4Lbil"; + + public Map getRoute(String origin, String destination) { + Map params = new HashMap<>(); + params.put("key", key); + params.put("origin", origin); + params.put("destination", destination); + HttpResponse response = HttpRequest.get("https://restapi.amap.com/v3/direction/walking") + .form(params) + .execute(); + String result = response.body(); + response.close(); + JSONObject route = JSONObject.parseObject(JSONObject.parseObject(result).getString("route")); + JSONArray paths = JSONArray.parseArray(route.getString("paths")); + JSONObject path = paths.getJSONObject(0); + String distance = path.getString("distance"); + String duration = path.getString("duration"); + Map map = new HashMap<>(); + map.put("distance", distance); + map.put("duration", duration); + map.put("steps", JSONArray.parseArray(path.getString("steps"), RouteStep.class)); + return map; + } + + public Map scanTicket(BufferedImage image) { + String base64Img = ImgUtil.toBase64(image, "jpg"); + SmartStructuralOCRV2Response resp; + try { + Credential cred = new Credential(secretId, secretKey); + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("ocr.tencentcloudapi.com"); + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + OcrClient client = new OcrClient(cred, "ap-shanghai", clientProfile); + SmartStructuralOCRV2Request req = new SmartStructuralOCRV2Request(); + req.setImageBase64(base64Img); + String[] itemNames1 = {"登机口", "检票口"}; + req.setItemNames(itemNames1); + resp = client.SmartStructuralOCRV2(req); + } catch (TencentCloudSDKException e) { + throw new RuntimeException(e.getMessage()); + } + Map result = new HashMap<>(); + List groupInfoList = Arrays.stream(resp.getStructuralList()).toList(); + for (GroupInfo groupInfo : groupInfoList) { + List lineList = Arrays.stream(groupInfo.getGroups()).toList(); + for (LineInfo lineInfo : lineList) { + List itemList = Arrays.stream(lineInfo.getLines()).toList(); + for (ItemInfo info : itemList) { + if (info.getKey() != null && info.getValue() != null) { + result.put(String.valueOf(info.getKey().getAutoName()), info.getValue().getAutoContent()); + } + } + } + } + return result; + } +} diff --git a/navigate-8432/src/main/java/com/ivmiku/tutorial/utils/GlobalExceptionHandler.java b/navigate-8432/src/main/java/com/ivmiku/tutorial/utils/GlobalExceptionHandler.java new file mode 100644 index 0000000..bc0f099 --- /dev/null +++ b/navigate-8432/src/main/java/com/ivmiku/tutorial/utils/GlobalExceptionHandler.java @@ -0,0 +1,61 @@ +package com.ivmiku.tutorial.utils; + +import cn.dev33.satoken.exception.SaTokenException; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.fastjson2.JSON; +import com.ivmiku.tutorial.response.Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import java.sql.SQLException; +import java.text.ParseException; + +/** + * @author Aurora + */ +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(value = SaTokenException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public Object SaTokenExceptionHandler(SaTokenException e) { + log.error("SaTokenException:" + e.getLocalizedMessage()); + return JSON.toJSON(Result.error("身份认证错误:" + e.getMessage())); + } + + @ExceptionHandler(value = ParseException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public Object parseExceptionHandler(ParseException e) { + + log.error("ParseException:" + e.getLocalizedMessage()); + return JSON.toJSON(Result.error("请检查日期是否合法")); + } + + @ExceptionHandler(value = SQLException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public Object SQLExceptionHandler(SQLException e) { + log.error("SQLException:" + e.getLocalizedMessage()); + return JSON.toJSON(Result.error("数据库出错!(内部错误)\n" + e.getMessage())); + } + + @ExceptionHandler(value = BlockException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ResponseBody + public Object sentinelHandler(BlockException e) { + return JSON.toJSON(Result.error("系统繁忙,请稍后再试")); + } + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public Object exceptionHandler(Exception e) { + log.error("Exception:" + e.getLocalizedMessage()); + return JSON.toJSON(Result.error("服务器内部错误:" + e.getClass() + ":" + e.getMessage())); + } +} diff --git a/navigate-8432/src/main/resources/application-dep.properties b/navigate-8432/src/main/resources/application-dep.properties new file mode 100644 index 0000000..c84c07e --- /dev/null +++ b/navigate-8432/src/main/resources/application-dep.properties @@ -0,0 +1,19 @@ +spring.data.redis.host=redis +spring.data.redis.port=6379 +spring.data.redis.database=0 +spring.data.redis.password=Shuodedaoli114514 + +spring.application.name=navigate + +server.port=8432 + +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.username=root +spring.datasource.password=Shuodedaoli114514 +spring.datasource.url=jdbc:mysql://mysql:4514/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&ServerTimezone=Asia/Shanghai + +spring.cloud.nacos.discovery.server-addr=nacos:8848 +spring.cloud.nacos.discovery.enabled=true + +management.zipkin.tracing.endpoint=http://zipkin:9411/api/v2/spans +management.tracing.sampling.probability=1.0 \ No newline at end of file diff --git a/navigate-8432/src/main/resources/application-dev.properties b/navigate-8432/src/main/resources/application-dev.properties new file mode 100644 index 0000000..cc170df --- /dev/null +++ b/navigate-8432/src/main/resources/application-dev.properties @@ -0,0 +1,14 @@ +spring.data.redis.host=localhost +spring.data.redis.port=6379 +spring.data.redis.database=0 + +spring.application.name=navigate + +server.port=8432 + +dubbo.application.qos-enable=false + +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.datasource.username=root +spring.datasource.password=12345abcde +spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tutorial?useUnicode=true&characterEncoding=utf8&useSSL=false&ServerTimezone=Asia/Shanghai diff --git a/navigate-8432/src/main/resources/application.properties b/navigate-8432/src/main/resources/application.properties new file mode 100644 index 0000000..257b306 --- /dev/null +++ b/navigate-8432/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.profiles.active=dev \ No newline at end of file