userName 1 долоо хоног өмнө
commit
a96348c7c4

+ 33 - 0
.gitignore

@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/

+ 84 - 0
pom.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.zhentao</groupId>
+    <artifactId>hechenghangsale</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>hechenghangsale</name>
+    <description>hechenghangsale</description>
+    <properties>
+        <java.version>1.8</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <spring-boot.version>2.6.13</spring-boot.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.3.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+            <version>2.8.1</version>
+        </dependency>
+    </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${spring-boot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <mainClass>com.zhentao.HechenghangsaleApplication</mainClass>
+                    <skip>true</skip>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>repackage</id>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 19 - 0
src/main/java/com/zhentao/HechenghangsaleApplication.java

@@ -0,0 +1,19 @@
+package com.zhentao;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.kafka.annotation.EnableKafka;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@SpringBootApplication
+@MapperScan("com.zhentao.mapper")
+@EnableScheduling
+@EnableKafka
+public class HechenghangsaleApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(HechenghangsaleApplication.class, args);
+    }
+
+}

+ 27 - 0
src/main/java/com/zhentao/controller/GoodsController.java

@@ -0,0 +1,27 @@
+package com.zhentao.controller;
+
+import com.zhentao.dto.GoodsDto;
+import com.zhentao.service.GoodsService;
+import com.zhentao.vo.ResultVo;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("/goods")
+public class GoodsController {
+    @Resource
+    private GoodsService goodsService;
+
+    @RequestMapping("/addGoods")
+    public ResultVo addGoods(@RequestBody GoodsDto goodsDto){
+        return goodsService.addGoods(goodsDto);
+    }
+    @RequestMapping("/findGoods")
+    public ResultVo findGoods(@RequestBody GoodsDto goodsDto, @RequestHeader String reqId,@RequestHeader Long reqTime,@RequestHeader String appId){
+        return goodsService.findGoods(goodsDto,reqId,reqTime,appId);
+    }
+}

+ 51 - 0
src/main/java/com/zhentao/domain/Goods.java

@@ -0,0 +1,51 @@
+package com.zhentao.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Data;
+
+/**
+ * 
+ * @TableName goods
+ */
+@TableName(value ="goods")
+@Data
+public class Goods implements Serializable {
+    /**
+     * 
+     */
+    @TableId
+    private Long id;
+
+    /**
+     * 
+     */
+    private String goodsName;
+
+    /**
+     * 
+     */
+    private String descriptions;
+
+    /**
+     * 
+     */
+    private String goodsImg;
+
+    /**
+     * 
+     */
+    private String content;
+
+    /**
+     * 
+     */
+    private Date createTime;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 14 - 0
src/main/java/com/zhentao/domain/KafkaSend.java

@@ -0,0 +1,14 @@
+package com.zhentao.domain;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class KafkaSend {
+    private String msgId;
+    private String content;
+    private String msgtype;
+}

+ 14 - 0
src/main/java/com/zhentao/dto/GoodsDto.java

@@ -0,0 +1,14 @@
+package com.zhentao.dto;
+
+import lombok.Data;
+import org.springframework.web.multipart.MultipartFile;
+
+@Data
+public class GoodsDto {
+    private Long goodsId;
+    private String sign;
+    private String goodsName;
+    private String descriptions;
+    private MultipartFile goodsImg;
+    private String content;
+}

+ 18 - 0
src/main/java/com/zhentao/mapper/GoodsMapper.java

@@ -0,0 +1,18 @@
+package com.zhentao.mapper;
+
+import com.zhentao.domain.Goods;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author 31810
+* @description 针对表【goods】的数据库操作Mapper
+* @createDate 2025-05-16 09:17:25
+* @Entity com.zhentao.domain.Goods
+*/
+public interface GoodsMapper extends BaseMapper<Goods> {
+
+}
+
+
+
+

+ 18 - 0
src/main/java/com/zhentao/service/GoodsService.java

@@ -0,0 +1,18 @@
+package com.zhentao.service;
+
+import com.zhentao.domain.Goods;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zhentao.dto.GoodsDto;
+import com.zhentao.vo.ResultVo;
+
+/**
+* @author 31810
+* @description 针对表【goods】的数据库操作Service
+* @createDate 2025-05-16 09:17:25
+*/
+public interface GoodsService extends IService<Goods> {
+
+    ResultVo addGoods(GoodsDto goodsDto);
+
+    ResultVo findGoods(GoodsDto goodsDto, String reqId, Long reqTime, String appId);
+}

+ 70 - 0
src/main/java/com/zhentao/service/impl/GoodsServiceImpl.java

@@ -0,0 +1,70 @@
+package com.zhentao.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zhentao.domain.Goods;
+import com.zhentao.dto.GoodsDto;
+import com.zhentao.service.GoodsService;
+import com.zhentao.mapper.GoodsMapper;
+import com.zhentao.util.SnowflakeIdGenerator;
+import com.zhentao.vo.ResultVo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.DigestUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+* @author 31810
+* @description 针对表【goods】的数据库操作Service实现
+* @createDate 2025-05-16 09:17:25
+*/
+@Service
+public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods>
+    implements GoodsService{
+    @Autowired
+    private GoodsMapper goodsMapper;
+    private static final String APP_SECRET="123";
+    @Override
+    public ResultVo addGoods(GoodsDto goodsDto) {
+        Goods goods=new Goods();
+        if(goodsDto.getGoodsName()!=null){
+            goods.setGoodsName(goodsDto.getGoodsName());
+        }
+        if(goodsDto.getGoodsImg()!=null){
+            goods.setGoodsImg(goodsDto.getGoodsImg().getOriginalFilename());
+        }
+        if(goodsDto.getContent()!=null){
+            goods.setContent(goodsDto.getContent());
+        }
+        goods.setId(SnowflakeIdGenerator.getSnowId());
+        goodsMapper.insert(goods);
+        return ResultVo.OK();
+    }
+
+    @Override
+    public ResultVo findGoods(GoodsDto goodsDto, String reqId, Long reqTime, String appId) {
+        Map<String,Object>map=new TreeMap<>();
+        map.put("reqId",reqId);
+        map.put("goodsId",goodsDto.getGoodsId());
+        map.put("reqTime",reqTime);
+        map.put("appId",appId);
+        StringBuilder stringBuilder=new StringBuilder();
+        for (Map.Entry<String,Object> m:map.entrySet()) {
+            stringBuilder.append(m.getKey()).append("=").append(m.getValue()).append("&");
+        }
+        stringBuilder.append("key").append(APP_SECRET);
+        String md5Sign= DigestUtils.md5DigestAsHex(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
+        if(md5Sign.equals(goodsDto.getSign())){
+            Long goodsId = goodsDto.getGoodsId();
+            Goods goods = goodsMapper.selectById(goodsId);
+            return ResultVo.OK(goods.getGoodsName());
+        }
+        return new ResultVo(1002,"验签失败",null);
+    }
+}
+
+
+
+

+ 31 - 0
src/main/java/com/zhentao/tast/KafkaTask.java

@@ -0,0 +1,31 @@
+package com.zhentao.tast;
+
+import com.zhentao.domain.KafkaSend;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.annotation.KafkaHandler;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.UUID;
+
+@Component
+public class KafkaTask {
+    @Autowired
+    private KafkaTemplate<String,String>kafkaTemplate;
+    @Scheduled(fixedRate = 60000)
+    public void sendMessage(){
+        KafkaSend kafkaSend=new KafkaSend();
+        kafkaSend.setContent("考试消费信息");
+        kafkaSend.setMsgId(UUID.randomUUID().toString().replace("-",""));
+        kafkaSend.setMsgtype("type");
+        kafkaTemplate.send("test",kafkaSend.getContent());
+    }
+
+    @KafkaListener(topics = "test")
+    public void listener(String message){
+        System.out.println("kafka消费了,信息是"+message);
+    }
+}

+ 136 - 0
src/main/java/com/zhentao/util/SnowflakeIdGenerator.java

@@ -0,0 +1,136 @@
+package com.zhentao.util;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+public class SnowflakeIdGenerator {
+    // 基础配置(Java 8+)
+    private static final long EPOCH = 1288834974657L; // 2010-11-04 00:00:00 UTC
+    private static final int DATACENTER_ID_BITS = 5;
+    private static final int WORKER_ID_BITS = 5;
+    private static final int SEQUENCE_BITS = 12;
+    // 位运算掩码
+    private static final long DATACENTER_ID_MASK = (1L << DATACENTER_ID_BITS) - 1;
+    private static final long WORKER_ID_MASK = (1L << WORKER_ID_BITS) - 1;
+    private static final long SEQUENCE_MASK = (1L << SEQUENCE_BITS) - 1;
+
+    // 位移偏移量
+    private static final int WORKER_ID_SHIFT = SEQUENCE_BITS;
+    private static final int DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
+    private static final int TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
+
+    private final long datacenterId;
+    private final long workerId;
+    private long sequence = 0L;
+    private long lastTimestamp = -1L;
+
+    private final Object lock = new Object();
+
+    public SnowflakeIdGenerator(long datacenterId, long workerId) {
+        if ((datacenterId & DATACENTER_ID_MASK) != datacenterId) {
+            throw new IllegalArgumentException("DataCenter ID 必须在 0-31 之间");
+        }
+        if ((workerId & WORKER_ID_MASK) != workerId) {
+            throw new IllegalArgumentException("Worker ID 必须在 0-31 之间");
+        }
+        this.datacenterId = datacenterId;
+        this.workerId = workerId;
+    }
+
+    public synchronized long nextId() {
+        long currentTimestamp = timeGen();
+
+        if (currentTimestamp < lastTimestamp) {
+            throw new IllegalStateException(
+                    String.format("时钟回退 %d 毫秒,禁止生成ID(上次: %d,当前: %d)",
+                            lastTimestamp - currentTimestamp, lastTimestamp, currentTimestamp));
+        }
+
+        if (currentTimestamp == lastTimestamp) {
+            sequence = (sequence + 1) & SEQUENCE_MASK;
+            if (sequence == 0) {
+                currentTimestamp = waitNextMillis(lastTimestamp);
+            }
+        } else {
+            sequence = 0;
+        }
+
+        lastTimestamp = currentTimestamp;
+
+        return ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) |
+                (datacenterId << DATACENTER_ID_SHIFT) |
+                (workerId << WORKER_ID_SHIFT) |
+                sequence;
+    }
+
+    private long waitNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = System.currentTimeMillis(); // 改用更可靠的时间源
+        }
+        return timestamp;
+    }
+
+    private long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    // 添加 parseId 方法
+    public static SnowflakeMeta parseId(long snowflakeId) {
+        long sequence = snowflakeId & SEQUENCE_MASK;
+        long workerId = (snowflakeId >> WORKER_ID_SHIFT) & WORKER_ID_MASK;
+        long datacenterId = (snowflakeId >> DATACENTER_ID_SHIFT) & DATACENTER_ID_MASK;
+        long timestamp = (snowflakeId >> TIMESTAMP_SHIFT) + EPOCH;
+
+        return new SnowflakeMeta(
+                timestamp,
+                datacenterId,
+                workerId,
+                sequence,
+                LocalDateTime.ofEpochSecond(timestamp / 1000, 0, ZoneOffset.ofHours(8))
+        );
+    }
+    public static Long getSnowId(){
+        SnowflakeIdGenerator generator=new SnowflakeIdGenerator(1,1);
+        Long id=generator.nextId();
+        SnowflakeMeta meta=SnowflakeIdGenerator.parseId(id);
+        return id;
+    }
+    // ---------------- 修复:添加完整的getter方法 ----------------
+    public static class SnowflakeMeta {
+        private final long timestamp;
+        private final long datacenterId;
+        private final long workerId;
+        private final long sequence;
+        private final LocalDateTime dateTime;
+
+        public SnowflakeMeta(long timestamp, long datacenterId, long workerId, long sequence, LocalDateTime dateTime) {
+            this.timestamp = timestamp;
+            this.datacenterId = datacenterId;
+            this.workerId = workerId;
+            this.sequence = sequence;
+            this.dateTime = dateTime;
+        }
+
+        // 显式定义getter(修复爆红)
+        public long getTimestamp() {
+            return timestamp;
+        }
+
+        public long getDatacenterId() {
+            return datacenterId;
+        }
+
+        public long getWorkerId() {
+            return workerId;
+        }
+
+        public long getSequence() {
+            return sequence;
+        }
+
+        public LocalDateTime getDateTime() {
+            return dateTime;
+        }
+    }
+}

+ 29 - 0
src/main/java/com/zhentao/vo/ResultVo.java

@@ -0,0 +1,29 @@
+package com.zhentao.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ResultVo {
+    private Integer code;
+    private String message;
+    private Object data;
+    public static ResultVo OK(){
+        return new ResultVo(200,"操作成功", null);
+    }
+
+    public static ResultVo OK(Object data){
+        return new ResultVo(200,"操作成功",data);
+    }
+
+    public static ResultVo ERROR(){
+        return new ResultVo(400,"操作失败",null);
+    }
+
+    public static ResultVo ERROR(Object data){
+        return new ResultVo(400,"操作失败",data);
+    }
+}

+ 20 - 0
src/main/resources/application.yml

@@ -0,0 +1,20 @@
+server:
+  port: 9527
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql:///kaoshi?serverTimezone=UTC
+    username: root
+    password: hch030923
+  kafka:
+    producer:
+      key-serializer: org.apache.kafka.common.serialization.StringSerializer
+      value-serializer: org.apache.kafka.common.serialization.StringSerializer
+    consumer:
+      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
+      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
+      group-id: test
+    bootstrap-servers: 127.0.0.1:9092
+mybatis-plus:
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

+ 20 - 0
src/main/resources/mapper/GoodsMapper.xml

@@ -0,0 +1,20 @@
+<?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.zhentao.mapper.GoodsMapper">
+
+    <resultMap id="BaseResultMap" type="com.zhentao.domain.Goods">
+            <id property="id" column="id" jdbcType="BIGINT"/>
+            <result property="goodsName" column="goods_name" jdbcType="VARCHAR"/>
+            <result property="descriptions" column="descriptions" jdbcType="VARCHAR"/>
+            <result property="goodsImg" column="goods_img" jdbcType="VARCHAR"/>
+            <result property="content" column="content" jdbcType="VARCHAR"/>
+            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,goods_name,descriptions,
+        goods_img,content,create_time
+    </sql>
+</mapper>

+ 13 - 0
src/test/java/com/zhentao/HechenghangsaleApplicationTests.java

@@ -0,0 +1,13 @@
+package com.zhentao;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class HechenghangsaleApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}