1.0
This commit is contained in:
33
旧的java项目/.gitignore
vendored
Normal file
33
旧的java项目/.gitignore
vendored
Normal file
@@ -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/
|
||||
BIN
旧的java项目/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
旧的java项目/.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
旧的java项目/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
旧的java项目/.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
||||
120
旧的java项目/AGENTS.md
Normal file
120
旧的java项目/AGENTS.md
Normal file
@@ -0,0 +1,120 @@
|
||||
AGENTS.md for this repository
|
||||
|
||||
Purpose
|
||||
- This document guides agent-like contributors (human or AI) on how to build, lint, test, and style the codebase.
|
||||
- It also captures preferences or constraints used by the team and by automated agents operating in this repo.
|
||||
|
||||
Scope
|
||||
- Build, test, and lint commands for common environments (Node/TS, Python, Go, Rust, Java).
|
||||
- Code style guidelines: imports, formatting, types, naming, error handling, tests, and documentation.
|
||||
- Cursor rules and Copilot rules inclusion if present in the repo.
|
||||
- How to handle running a single test and how to extend tests locally.
|
||||
|
||||
1) Quick start: common commands
|
||||
- Build (preferred entry point):
|
||||
- Node/TypeScript: npm run build (or yarn build)
|
||||
- Python: python -m build or your project-specific build script
|
||||
- Go: go build ./...
|
||||
- Rust: cargo build
|
||||
- Lint:
|
||||
- Node/TypeScript: npm run lint (or yarn lint)
|
||||
- Python: ruff check . | flake8 or your project’s linter
|
||||
- Go: golangci-lint run
|
||||
- Rust: cargo clippy
|
||||
- Test:
|
||||
- Node/TS: npm test (or yarn test)
|
||||
- Python: pytest
|
||||
- Go: go test ./...
|
||||
- Rust: cargo test
|
||||
- Note: If your repo uses a mixed tech stack, prefer using the language-specific script in package.json or equivalent courier scripts.
|
||||
|
||||
2) Run a single test (typical patterns)
|
||||
- Node / Jest
|
||||
- Run a specific test by name: npm test -- -t "should render the component"
|
||||
- Run a specific file: npm test -- path/to/file.test.js
|
||||
- Python / Pytest
|
||||
- Run tests matching a keyword: pytest -k "test_name_substring" -q
|
||||
- Run a specific file: pytest tests/test_module.py -q
|
||||
- Go
|
||||
- Run a single test by name: go test -run TestName ./...
|
||||
- Rust / Cargo
|
||||
- Exact test: cargo test -- --exact TestName
|
||||
- Run a file-like subset: cargo test -- 'pattern'
|
||||
- Java / Maven or Gradle
|
||||
- Maven: mvn -Dtest=MyTest#testMethod test
|
||||
- Gradle: ./gradlew test --tests "com.example.MyTest.testMethod"
|
||||
|
||||
3) Code style guidelines
|
||||
<A) Imports and modules>
|
||||
- Group imports into three blocks: standard library, third-party, and first-party modules.
|
||||
- Order blocks alphabetically within each group; separate blocks with a newline.
|
||||
- Avoid wildcard imports; prefer explicit imports.
|
||||
- For TS/JS, prefer absolute/alias imports over relative when it improves clarity.
|
||||
|
||||
<B) Formatting and tooling>
|
||||
- Use the project’s formatter (Prettier, gofmt, black, etc.) with the configured settings.
|
||||
- Respect the repository’s line length (commonly 100-120 chars). Break long lines at logical points.
|
||||
- Use semicolons consistently if the project enforces them; otherwise adhere to the established style.
|
||||
- Enable and respect lint rules; fix all autofixable issues during code edits.
|
||||
|
||||
<C) Types and APIs>
|
||||
- In TypeScript, enable strict type checking; prefer interfaces for public APIs and type aliases for shapes.
|
||||
- Use readonly modifiers where possible to express intent and optimize immutability guarantees.
|
||||
- Prefer explicit return types for exported functions and public APIs.
|
||||
- Avoid any where possible; if necessary, use unknown with proper checks.
|
||||
|
||||
<D) Naming conventions>
|
||||
- Variables and functions: camelCase
|
||||
- Classes and types: PascalCase
|
||||
- Constants: UPPER_SNAKE_CASE
|
||||
- File and module names: kebab-case or snake_case, consistent with project convention
|
||||
|
||||
<E) Error handling>
|
||||
- Do not swallow errors; attach context when rethrowing (e.g., throw new Error(`Context: ${err.message}`)).
|
||||
- Propagate errors to callers with meaningful messages.
|
||||
- Use try/catch around IO-bound or network-bound operations and ensure resources are released in finally or via finally-like blocks.
|
||||
|
||||
<F) Async/Promises>
|
||||
- Prefer async/await syntax for readability.
|
||||
- Handle rejections at the call site when possible; avoid unhandled promises.
|
||||
- Use Promise.all when performing independent async tasks, but catch and handle failures gracefully.
|
||||
|
||||
<G) Tests>
|
||||
- Tests should be fast, deterministic, and hermetic.
|
||||
- Use descriptive test names and structure (Arrange-Act-Assert patterns where helpful).
|
||||
- Isolate external dependencies; mock/stub network/db calls effectively.
|
||||
- Include tests for error paths and boundary conditions.
|
||||
|
||||
<H) Documentation and comments>
|
||||
- Document non-obvious logic with concise comments; avoid obvious boilerplate.
|
||||
- Public APIs should have JSDoc / TSdoc-style comments describing inputs, outputs, and side effects.
|
||||
- Update or add READMEs where necessary to reflect changes in behavior.
|
||||
|
||||
<I) Security and compliance>
|
||||
- Do not log sensitive data; mask secrets in logs.
|
||||
- Validate inputs and sanitize outputs where appropriate.
|
||||
- Treat untrusted data carefully; avoid code paths that execute untrusted input without validation.
|
||||
|
||||
4) Cursor and Copilot rules
|
||||
- Cursor rules: If this repo uses Cursor tooling, its rules can live under .cursor/rules/ or .cursorrules. Copy or adapt them into this document when agents are created.
|
||||
- Copilot rules: If there is .github/copilot-instructions.md, follow its guidance and ensure code generation adheres to the outlined constraints.
|
||||
- If the repo contains these files, consider linking to them here and summarizing any special constraints applicable to agents.
|
||||
|
||||
5) Git workflow and contribution notes
|
||||
- Do not modify dependencies without explicit approval.
|
||||
- Keep commits small and focused; write 1-2 sentence messages describing why a change was made, not just what changed.
|
||||
- For AGENTS.md updates, include a short rationale in the commit message.
|
||||
- Prefer small, reviewed edits over sweeping rewrites.
|
||||
|
||||
6) Local integration guidance
|
||||
- Run: npm install or yarn to install deps before building/tests.
|
||||
- For multi-language repos, ensure the local environment has language runtimes and tooling installed (Node, Python, Go, Rust, etc.).
|
||||
- Use a clean environment (e.g., nvm, virtualenv) to avoid cross-project contamination.
|
||||
|
||||
7) Example usage scenarios
|
||||
- A single-file feature: create a minimal unit test, run npm test -- -t "feature X" to validate.
|
||||
- A refactor: run lint and then a subset of tests; fix issues flagged by lints before merging.
|
||||
- A CI-like dry run: run npm ci; npm run build; npm test; and report failures with minimal noise.
|
||||
|
||||
Notes
|
||||
- If you want me to tailor this file to the exact repo, I can incorporate the actual existing AGENTS.md content (if present) or sync with Cursor/Copilot rules after inspecting the repo. Right now this is a solid, language-agnostic baseline.
|
||||
41
旧的java项目/itcast/client/ChatClient.java
Normal file
41
旧的java项目/itcast/client/ChatClient.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package cn.itcast.client;
|
||||
|
||||
import cn.itcast.protocol.MessageCodecSharable;
|
||||
import cn.itcast.protocol.ProcotolFrameDecoder;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ChatClient {
|
||||
public static void main(String[] args) {
|
||||
NioEventLoopGroup group = new NioEventLoopGroup();
|
||||
LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
|
||||
MessageCodecSharable MESSAGE_CODEC = new MessageCodecSharable();
|
||||
try {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.channel(NioSocketChannel.class);
|
||||
bootstrap.group(group);
|
||||
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ch.pipeline().addLast(new ProcotolFrameDecoder());
|
||||
ch.pipeline().addLast(LOGGING_HANDLER);
|
||||
ch.pipeline().addLast(MESSAGE_CODEC);
|
||||
}
|
||||
});
|
||||
Channel channel = bootstrap.connect("localhost", 9020).sync().channel();
|
||||
channel.closeFuture().sync();
|
||||
} catch (Exception e) {
|
||||
// log.error("client error", e);
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
||||
19
旧的java项目/itcast/message/AbstractResponseMessage.java
Normal file
19
旧的java项目/itcast/message/AbstractResponseMessage.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public abstract class AbstractResponseMessage extends Message {
|
||||
private boolean success;
|
||||
private String reason;
|
||||
|
||||
public AbstractResponseMessage() {
|
||||
}
|
||||
|
||||
public AbstractResponseMessage(boolean success, String reason) {
|
||||
this.success = success;
|
||||
this.reason = reason;
|
||||
}
|
||||
}
|
||||
26
旧的java项目/itcast/message/ChatRequestMessage.java
Normal file
26
旧的java项目/itcast/message/ChatRequestMessage.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class ChatRequestMessage extends Message {
|
||||
private String content;
|
||||
private String to;
|
||||
private String from;
|
||||
|
||||
public ChatRequestMessage() {
|
||||
}
|
||||
|
||||
public ChatRequestMessage(String from, String to, String content) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return ChatRequestMessage;
|
||||
}
|
||||
}
|
||||
26
旧的java项目/itcast/message/ChatResponseMessage.java
Normal file
26
旧的java项目/itcast/message/ChatResponseMessage.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class ChatResponseMessage extends AbstractResponseMessage {
|
||||
|
||||
private String from;
|
||||
private String content;
|
||||
|
||||
public ChatResponseMessage(boolean success, String reason) {
|
||||
super(success, reason);
|
||||
}
|
||||
|
||||
public ChatResponseMessage(String from, String content) {
|
||||
this.from = from;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return ChatResponseMessage;
|
||||
}
|
||||
}
|
||||
23
旧的java项目/itcast/message/GroupChatRequestMessage.java
Normal file
23
旧的java项目/itcast/message/GroupChatRequestMessage.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupChatRequestMessage extends Message {
|
||||
private String content;
|
||||
private String groupName;
|
||||
private String from;
|
||||
|
||||
public GroupChatRequestMessage(String from, String groupName, String content) {
|
||||
this.content = content;
|
||||
this.groupName = groupName;
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupChatRequestMessage;
|
||||
}
|
||||
}
|
||||
24
旧的java项目/itcast/message/GroupChatResponseMessage.java
Normal file
24
旧的java项目/itcast/message/GroupChatResponseMessage.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupChatResponseMessage extends AbstractResponseMessage {
|
||||
private String from;
|
||||
private String content;
|
||||
|
||||
public GroupChatResponseMessage(boolean success, String reason) {
|
||||
super(success, reason);
|
||||
}
|
||||
|
||||
public GroupChatResponseMessage(String from, String content) {
|
||||
this.from = from;
|
||||
this.content = content;
|
||||
}
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupChatResponseMessage;
|
||||
}
|
||||
}
|
||||
23
旧的java项目/itcast/message/GroupCreateRequestMessage.java
Normal file
23
旧的java项目/itcast/message/GroupCreateRequestMessage.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupCreateRequestMessage extends Message {
|
||||
private String groupName;
|
||||
private Set<String> members;
|
||||
|
||||
public GroupCreateRequestMessage(String groupName, Set<String> members) {
|
||||
this.groupName = groupName;
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupCreateRequestMessage;
|
||||
}
|
||||
}
|
||||
18
旧的java项目/itcast/message/GroupCreateResponseMessage.java
Normal file
18
旧的java项目/itcast/message/GroupCreateResponseMessage.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupCreateResponseMessage extends AbstractResponseMessage {
|
||||
|
||||
public GroupCreateResponseMessage(boolean success, String reason) {
|
||||
super(success, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupCreateResponseMessage;
|
||||
}
|
||||
}
|
||||
22
旧的java项目/itcast/message/GroupJoinRequestMessage.java
Normal file
22
旧的java项目/itcast/message/GroupJoinRequestMessage.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupJoinRequestMessage extends Message {
|
||||
private String groupName;
|
||||
|
||||
private String username;
|
||||
|
||||
public GroupJoinRequestMessage(String username, String groupName) {
|
||||
this.groupName = groupName;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupJoinRequestMessage;
|
||||
}
|
||||
}
|
||||
18
旧的java项目/itcast/message/GroupJoinResponseMessage.java
Normal file
18
旧的java项目/itcast/message/GroupJoinResponseMessage.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupJoinResponseMessage extends AbstractResponseMessage {
|
||||
|
||||
public GroupJoinResponseMessage(boolean success, String reason) {
|
||||
super(success, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupJoinResponseMessage;
|
||||
}
|
||||
}
|
||||
19
旧的java项目/itcast/message/GroupMembersRequestMessage.java
Normal file
19
旧的java项目/itcast/message/GroupMembersRequestMessage.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupMembersRequestMessage extends Message {
|
||||
private String groupName;
|
||||
|
||||
public GroupMembersRequestMessage(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupMembersRequestMessage;
|
||||
}
|
||||
}
|
||||
22
旧的java项目/itcast/message/GroupMembersResponseMessage.java
Normal file
22
旧的java项目/itcast/message/GroupMembersResponseMessage.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupMembersResponseMessage extends Message {
|
||||
|
||||
private Set<String> members;
|
||||
|
||||
public GroupMembersResponseMessage(Set<String> members) {
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupMembersResponseMessage;
|
||||
}
|
||||
}
|
||||
22
旧的java项目/itcast/message/GroupQuitRequestMessage.java
Normal file
22
旧的java项目/itcast/message/GroupQuitRequestMessage.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupQuitRequestMessage extends Message {
|
||||
private String groupName;
|
||||
|
||||
private String username;
|
||||
|
||||
public GroupQuitRequestMessage(String username, String groupName) {
|
||||
this.groupName = groupName;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupQuitRequestMessage;
|
||||
}
|
||||
}
|
||||
17
旧的java项目/itcast/message/GroupQuitResponseMessage.java
Normal file
17
旧的java项目/itcast/message/GroupQuitResponseMessage.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class GroupQuitResponseMessage extends AbstractResponseMessage {
|
||||
public GroupQuitResponseMessage(boolean success, String reason) {
|
||||
super(success, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return GroupQuitResponseMessage;
|
||||
}
|
||||
}
|
||||
26
旧的java项目/itcast/message/LoginRequestMessage.java
Normal file
26
旧的java项目/itcast/message/LoginRequestMessage.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class LoginRequestMessage extends Message {
|
||||
private String username;
|
||||
private String password;
|
||||
private String nickname;
|
||||
|
||||
public LoginRequestMessage() {
|
||||
}
|
||||
|
||||
public LoginRequestMessage(String username, String password, String nickname) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return LoginRequestMessage;
|
||||
}
|
||||
}
|
||||
13
旧的java项目/itcast/message/LoginResponseMessage.java
Normal file
13
旧的java项目/itcast/message/LoginResponseMessage.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class LoginResponseMessage extends AbstractResponseMessage {
|
||||
@Override
|
||||
public int getMessageType() {
|
||||
return LoginResponseMessage;
|
||||
}
|
||||
}
|
||||
54
旧的java项目/itcast/message/Message.java
Normal file
54
旧的java项目/itcast/message/Message.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package cn.itcast.message;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public abstract class Message implements Serializable {
|
||||
|
||||
public static Class<?> getMessageClass(int messageType) {
|
||||
return messageClasses.get(messageType);
|
||||
}
|
||||
|
||||
private int sequenceId;
|
||||
|
||||
private int messageType;
|
||||
|
||||
public abstract int getMessageType();
|
||||
|
||||
public static final int LoginRequestMessage = 0;
|
||||
public static final int LoginResponseMessage = 1;
|
||||
public static final int ChatRequestMessage = 2;
|
||||
public static final int ChatResponseMessage = 3;
|
||||
public static final int GroupCreateRequestMessage = 4;
|
||||
public static final int GroupCreateResponseMessage = 5;
|
||||
public static final int GroupJoinRequestMessage = 6;
|
||||
public static final int GroupJoinResponseMessage = 7;
|
||||
public static final int GroupQuitRequestMessage = 8;
|
||||
public static final int GroupQuitResponseMessage = 9;
|
||||
public static final int GroupChatRequestMessage = 10;
|
||||
public static final int GroupChatResponseMessage = 11;
|
||||
public static final int GroupMembersRequestMessage = 12;
|
||||
public static final int GroupMembersResponseMessage = 13;
|
||||
private static final Map<Integer, Class<?>> messageClasses = new HashMap<>();
|
||||
|
||||
static {
|
||||
messageClasses.put(LoginRequestMessage, LoginRequestMessage.class);
|
||||
messageClasses.put(LoginResponseMessage, LoginResponseMessage.class);
|
||||
messageClasses.put(ChatRequestMessage, ChatRequestMessage.class);
|
||||
messageClasses.put(ChatResponseMessage, ChatResponseMessage.class);
|
||||
messageClasses.put(GroupCreateRequestMessage, GroupCreateRequestMessage.class);
|
||||
messageClasses.put(GroupCreateResponseMessage, GroupCreateResponseMessage.class);
|
||||
messageClasses.put(GroupJoinRequestMessage, GroupJoinRequestMessage.class);
|
||||
messageClasses.put(GroupJoinResponseMessage, GroupJoinResponseMessage.class);
|
||||
messageClasses.put(GroupQuitRequestMessage, GroupQuitRequestMessage.class);
|
||||
messageClasses.put(GroupQuitResponseMessage, GroupQuitResponseMessage.class);
|
||||
messageClasses.put(GroupChatRequestMessage, GroupChatRequestMessage.class);
|
||||
messageClasses.put(GroupChatResponseMessage, GroupChatResponseMessage.class);
|
||||
messageClasses.put(GroupMembersRequestMessage, GroupMembersRequestMessage.class);
|
||||
messageClasses.put(GroupMembersResponseMessage, GroupMembersResponseMessage.class);
|
||||
}
|
||||
}
|
||||
62
旧的java项目/itcast/protocol/MessageCodec.java
Normal file
62
旧的java项目/itcast/protocol/MessageCodec.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package cn.itcast.protocol;
|
||||
|
||||
import cn.itcast.message.Message;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageCodec;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@ChannelHandler.Sharable
|
||||
public class MessageCodec extends ByteToMessageCodec<Message> {
|
||||
|
||||
@Override
|
||||
public void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
|
||||
// // 1. 4 字节的魔数
|
||||
// out.writeBytes(new byte[]{1, 2, 3, 4});
|
||||
// // 2. 1 字节的版本,
|
||||
// out.writeByte(1);
|
||||
// // 3. 1 字节的序列化方式 jdk 0 , json 1
|
||||
// out.writeByte(0);
|
||||
// // 4. 1 字节的指令类型
|
||||
// out.writeByte(msg.getMessageType());
|
||||
// // 5. 4 个字节
|
||||
//// out.writeInt(msg.getSequenceId());
|
||||
// // 无意义,对齐填充
|
||||
// out.writeByte(0xff);
|
||||
// // 6. 获取内容的字节数组
|
||||
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
// ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
// oos.writeObject(msg);
|
||||
// byte[] bytes = bos.toByteArray();
|
||||
// // 7. 长度
|
||||
// out.writeInt(bytes.length);
|
||||
// // 8. 写入内容
|
||||
// out.writeBytes(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
int magicNum = in.readInt();
|
||||
byte version = in.readByte();
|
||||
byte serializerType = in.readByte();
|
||||
byte messageType = in.readByte();
|
||||
int sequenceId = in.readInt();
|
||||
in.readByte();
|
||||
int length = in.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
in.readBytes(bytes, 0, length);
|
||||
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
|
||||
Message message = (Message) ois.readObject();
|
||||
// log.debug("{}, {}, {}, {}, {}, {}", magicNum, version, serializerType, messageType, sequenceId, length);
|
||||
// log.debug("{}", message);
|
||||
out.add(message);
|
||||
}
|
||||
}
|
||||
66
旧的java项目/itcast/protocol/MessageCodecSharable.java
Normal file
66
旧的java项目/itcast/protocol/MessageCodecSharable.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package cn.itcast.protocol;
|
||||
|
||||
import cn.itcast.message.Message;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageCodec;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@ChannelHandler.Sharable
|
||||
/**
|
||||
* 必须和 LengthFieldBasedFrameDecoder 一起使用,确保接到的 ByteBuf 消息是完整的
|
||||
*/
|
||||
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, Message> {
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
|
||||
// ByteBuf out = ctx.alloc().buffer();
|
||||
// // 1. 4 字节的魔数
|
||||
// out.writeBytes(new byte[]{1, 2, 3, 4});
|
||||
// // 2. 1 字节的版本,
|
||||
// out.writeByte(1);
|
||||
// // 3. 1 字节的序列化方式 jdk 0 , json 1
|
||||
// out.writeByte(0);
|
||||
// // 4. 1 字节的指令类型
|
||||
// out.writeByte(msg.getMessageType());
|
||||
// // 5. 4 个字节
|
||||
// out.writeInt(msg.getSequenceId());
|
||||
// // 无意义,对齐填充
|
||||
// out.writeByte(0xff);
|
||||
// // 6. 获取内容的字节数组
|
||||
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
// ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
// oos.writeObject(msg);
|
||||
// byte[] bytes = bos.toByteArray();
|
||||
// // 7. 长度
|
||||
// out.writeInt(bytes.length);
|
||||
// // 8. 写入内容
|
||||
// out.writeBytes(bytes);
|
||||
// outList.add(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
int magicNum = in.readInt();
|
||||
byte version = in.readByte();
|
||||
byte serializerType = in.readByte();
|
||||
byte messageType = in.readByte();
|
||||
int sequenceId = in.readInt();
|
||||
in.readByte();
|
||||
int length = in.readInt();
|
||||
byte[] bytes = new byte[length];
|
||||
in.readBytes(bytes, 0, length);
|
||||
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
|
||||
Message message = (Message) ois.readObject();
|
||||
// log.debug("{}, {}, {}, {}, {}, {}", magicNum, version, serializerType, messageType, sequenceId, length);
|
||||
// log.debug("{}", message);
|
||||
out.add(message);
|
||||
}
|
||||
}
|
||||
14
旧的java项目/itcast/protocol/ProcotolFrameDecoder.java
Normal file
14
旧的java项目/itcast/protocol/ProcotolFrameDecoder.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package cn.itcast.protocol;
|
||||
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
|
||||
public class ProcotolFrameDecoder extends LengthFieldBasedFrameDecoder {
|
||||
|
||||
public ProcotolFrameDecoder() {
|
||||
this(1024, 12, 4, 0, 0);
|
||||
}
|
||||
|
||||
public ProcotolFrameDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) {
|
||||
super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip);
|
||||
}
|
||||
}
|
||||
44
旧的java项目/itcast/server/ChatServer.java
Normal file
44
旧的java项目/itcast/server/ChatServer.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package cn.itcast.server;
|
||||
|
||||
import cn.itcast.protocol.MessageCodecSharable;
|
||||
import cn.itcast.protocol.ProcotolFrameDecoder;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class ChatServer {
|
||||
public static void main(String[] args) {
|
||||
NioEventLoopGroup boss = new NioEventLoopGroup();
|
||||
NioEventLoopGroup worker = new NioEventLoopGroup();
|
||||
LoggingHandler LOGGING_HANDLER = new LoggingHandler(LogLevel.DEBUG);
|
||||
MessageCodecSharable MESSAGE_CODEC = new MessageCodecSharable();
|
||||
try {
|
||||
ServerBootstrap serverBootstrap = new ServerBootstrap();
|
||||
serverBootstrap.channel(NioServerSocketChannel.class);
|
||||
serverBootstrap.group(boss, worker);
|
||||
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) throws Exception {
|
||||
ch.pipeline().addLast(new ProcotolFrameDecoder());
|
||||
ch.pipeline().addLast(LOGGING_HANDLER);
|
||||
ch.pipeline().addLast(MESSAGE_CODEC);
|
||||
}
|
||||
});
|
||||
Channel channel = serverBootstrap.bind(9020).sync().channel();
|
||||
channel.closeFuture().sync();
|
||||
} catch (InterruptedException e) {
|
||||
// log.error("server error", e);
|
||||
} finally {
|
||||
boss.shutdownGracefully();
|
||||
worker.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
旧的java项目/itcast/server/service/UserService.java
Normal file
15
旧的java项目/itcast/server/service/UserService.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package cn.itcast.server.service;
|
||||
|
||||
/**
|
||||
* 用户管理接口
|
||||
*/
|
||||
public interface UserService {
|
||||
|
||||
/**
|
||||
* 登录
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @return 登录成功返回 true, 否则返回 false
|
||||
*/
|
||||
boolean login(String username, String password);
|
||||
}
|
||||
10
旧的java项目/itcast/server/service/UserServiceFactory.java
Normal file
10
旧的java项目/itcast/server/service/UserServiceFactory.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package cn.itcast.server.service;
|
||||
|
||||
public abstract class UserServiceFactory {
|
||||
|
||||
private static UserService userService = new UserServiceMemoryImpl();
|
||||
|
||||
public static UserService getUserService() {
|
||||
return userService;
|
||||
}
|
||||
}
|
||||
25
旧的java项目/itcast/server/service/UserServiceMemoryImpl.java
Normal file
25
旧的java项目/itcast/server/service/UserServiceMemoryImpl.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package cn.itcast.server.service;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class UserServiceMemoryImpl implements UserService {
|
||||
private Map<String, String> allUserMap = new ConcurrentHashMap<>();
|
||||
|
||||
{
|
||||
allUserMap.put("zhangsan", "123");
|
||||
allUserMap.put("lisi", "123");
|
||||
allUserMap.put("wangwu", "123");
|
||||
allUserMap.put("zhaoliu", "123");
|
||||
allUserMap.put("qianqi", "123");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean login(String username, String password) {
|
||||
String pass = allUserMap.get(username);
|
||||
if (pass == null) {
|
||||
return false;
|
||||
}
|
||||
return pass.equals(password);
|
||||
}
|
||||
}
|
||||
24
旧的java项目/itcast/server/session/Group.java
Normal file
24
旧的java项目/itcast/server/session/Group.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package cn.itcast.server.session;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
/**
|
||||
* 聊天组,即聊天室
|
||||
*/
|
||||
public class Group {
|
||||
// 聊天室名称
|
||||
private String name;
|
||||
// 聊天室成员
|
||||
private Set<String> members;
|
||||
|
||||
public static final Group EMPTY_GROUP = new Group("empty", Collections.emptySet());
|
||||
|
||||
public Group(String name, Set<String> members) {
|
||||
this.name = name;
|
||||
this.members = members;
|
||||
}
|
||||
}
|
||||
57
旧的java项目/itcast/server/session/GroupSession.java
Normal file
57
旧的java项目/itcast/server/session/GroupSession.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package cn.itcast.server.session;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 聊天组会话管理接口
|
||||
*/
|
||||
public interface GroupSession {
|
||||
|
||||
/**
|
||||
* 创建一个聊天组, 如果不存在才能创建成功, 否则返回 null
|
||||
* @param name 组名
|
||||
* @param members 成员
|
||||
* @return 成功时返回组对象, 失败返回 null
|
||||
*/
|
||||
Group createGroup(String name, Set<String> members);
|
||||
|
||||
/**
|
||||
* 加入聊天组
|
||||
* @param name 组名
|
||||
* @param member 成员名
|
||||
* @return 如果组不存在返回 null, 否则返回组对象
|
||||
*/
|
||||
Group joinMember(String name, String member);
|
||||
|
||||
/**
|
||||
* 移除组成员
|
||||
* @param name 组名
|
||||
* @param member 成员名
|
||||
* @return 如果组不存在返回 null, 否则返回组对象
|
||||
*/
|
||||
Group removeMember(String name, String member);
|
||||
|
||||
/**
|
||||
* 移除聊天组
|
||||
* @param name 组名
|
||||
* @return 如果组不存在返回 null, 否则返回组对象
|
||||
*/
|
||||
Group removeGroup(String name);
|
||||
|
||||
/**
|
||||
* 获取组成员
|
||||
* @param name 组名
|
||||
* @return 成员集合, 没有成员会返回 empty set
|
||||
*/
|
||||
Set<String> getMembers(String name);
|
||||
|
||||
/**
|
||||
* 获取组成员的 channel 集合, 只有在线的 channel 才会返回
|
||||
* @param name 组名
|
||||
* @return 成员 channel 集合
|
||||
*/
|
||||
List<Channel> getMembersChannel(String name);
|
||||
}
|
||||
10
旧的java项目/itcast/server/session/GroupSessionFactory.java
Normal file
10
旧的java项目/itcast/server/session/GroupSessionFactory.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package cn.itcast.server.session;
|
||||
|
||||
public abstract class GroupSessionFactory {
|
||||
|
||||
private static GroupSession session = new GroupSessionMemoryImpl();
|
||||
|
||||
public static GroupSession getGroupSession() {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
55
旧的java项目/itcast/server/session/GroupSessionMemoryImpl.java
Normal file
55
旧的java项目/itcast/server/session/GroupSessionMemoryImpl.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package cn.itcast.server.session;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GroupSessionMemoryImpl implements GroupSession {
|
||||
private final Map<String, Group> groupMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Group createGroup(String name, Set<String> members) {
|
||||
Group group = new Group(name, members);
|
||||
return groupMap.putIfAbsent(name, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group joinMember(String name, String member) {
|
||||
return groupMap.computeIfPresent(name, (key, value) -> {
|
||||
// value.getMembers().add(member);
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group removeMember(String name, String member) {
|
||||
return groupMap.computeIfPresent(name, (key, value) -> {
|
||||
// value.getMembers().remove(member);
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group removeGroup(String name) {
|
||||
return groupMap.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getMembers(String name) {
|
||||
// return groupMap.getOrDefault(name, Group.EMPTY_GROUP).getMembers();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Channel> getMembersChannel(String name) {
|
||||
return getMembers(name).stream()
|
||||
.map(member -> SessionFactory.getSession().getChannel(member))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
46
旧的java项目/itcast/server/session/Session.java
Normal file
46
旧的java项目/itcast/server/session/Session.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package cn.itcast.server.session;
|
||||
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
/**
|
||||
* 会话管理接口
|
||||
*/
|
||||
public interface Session {
|
||||
|
||||
/**
|
||||
* 绑定会话
|
||||
* @param channel 哪个 channel 要绑定会话
|
||||
* @param username 会话绑定用户
|
||||
*/
|
||||
void bind(Channel channel, String username);
|
||||
|
||||
/**
|
||||
* 解绑会话
|
||||
* @param channel 哪个 channel 要解绑会话
|
||||
*/
|
||||
void unbind(Channel channel);
|
||||
|
||||
/**
|
||||
* 获取属性
|
||||
* @param channel 哪个 channel
|
||||
* @param name 属性名
|
||||
* @return 属性值
|
||||
*/
|
||||
Object getAttribute(Channel channel, String name);
|
||||
|
||||
/**
|
||||
* 设置属性
|
||||
* @param channel 哪个 channel
|
||||
* @param name 属性名
|
||||
* @param value 属性值
|
||||
*/
|
||||
void setAttribute(Channel channel, String name, Object value);
|
||||
|
||||
/**
|
||||
* 根据用户名获取 channel
|
||||
* @param username 用户名
|
||||
* @return channel
|
||||
*/
|
||||
Channel getChannel(String username);
|
||||
}
|
||||
10
旧的java项目/itcast/server/session/SessionFactory.java
Normal file
10
旧的java项目/itcast/server/session/SessionFactory.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package cn.itcast.server.session;
|
||||
|
||||
public abstract class SessionFactory {
|
||||
|
||||
private static Session session = new SessionMemoryImpl();
|
||||
|
||||
public static Session getSession() {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
47
旧的java项目/itcast/server/session/SessionMemoryImpl.java
Normal file
47
旧的java项目/itcast/server/session/SessionMemoryImpl.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package cn.itcast.server.session;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class SessionMemoryImpl implements Session {
|
||||
|
||||
private final Map<String, Channel> usernameChannelMap = new ConcurrentHashMap<>();
|
||||
private final Map<Channel, String> channelUsernameMap = new ConcurrentHashMap<>();
|
||||
private final Map<Channel,Map<String,Object>> channelAttributesMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void bind(Channel channel, String username) {
|
||||
usernameChannelMap.put(username, channel);
|
||||
channelUsernameMap.put(channel, username);
|
||||
channelAttributesMap.put(channel, new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(Channel channel) {
|
||||
String username = channelUsernameMap.remove(channel);
|
||||
usernameChannelMap.remove(username);
|
||||
channelAttributesMap.remove(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(Channel channel, String name) {
|
||||
return channelAttributesMap.get(channel).get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(Channel channel, String name, Object value) {
|
||||
channelAttributesMap.get(channel).put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel getChannel(String username) {
|
||||
return usernameChannelMap.get(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return usernameChannelMap.toString();
|
||||
}
|
||||
}
|
||||
316
旧的java项目/mvnw
vendored
Normal file
316
旧的java项目/mvnw
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`\\unset -f command; \\command -v java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||
188
旧的java项目/mvnw.cmd
vendored
Normal file
188
旧的java项目/mvnw.cmd
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% ^
|
||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||
%MAVEN_OPTS% ^
|
||||
%MAVEN_DEBUG_OPTS% ^
|
||||
-classpath %WRAPPER_JAR% ^
|
||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||
|
||||
cmd /C exit /B %ERROR_CODE%
|
||||
134
旧的java项目/pom.xml
Normal file
134
旧的java项目/pom.xml
Normal file
@@ -0,0 +1,134 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.6</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>sjkbf</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>sjkbf</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.16</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.coobird</groupId>
|
||||
<artifactId>thumbnailator</artifactId>
|
||||
<version>0.4.14</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
<!-- MyBatis-Plus Generator(改用官方版本) -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-generator</artifactId>
|
||||
<version>3.4.1</version>
|
||||
</dependency>
|
||||
<!-- freemarker 模板引擎(没有用原生的模板引擎)-->
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.31</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.7.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>3.5.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- JWT-->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>0.11.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.11.5</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
<version>2.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>1.15.3</version> <!-- 版本号可根据需要调整 -->
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.example.sjkbf;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author lnj
|
||||
* createTime 2018-11-07 22:37
|
||||
**/
|
||||
@Component
|
||||
public class ApplicationRunnerImpl implements ApplicationRunner {
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
|
||||
}
|
||||
}
|
||||
141
旧的java项目/src/main/java/com/example/sjkbf/CodeGenerator.java
Normal file
141
旧的java项目/src/main/java/com/example/sjkbf/CodeGenerator.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package com.example.sjkbf;
|
||||
|
||||
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.generator.AutoGenerator;
|
||||
import com.baomidou.mybatisplus.generator.InjectionConfig;
|
||||
import com.baomidou.mybatisplus.generator.config.*;
|
||||
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
|
||||
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
|
||||
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class CodeGenerator {
|
||||
|
||||
|
||||
//依赖
|
||||
|
||||
// compile group: 'com.baomidou', name: 'mybatis-plus-generator', version: '3.3.1.tmp'
|
||||
// compile group: 'org.freemarker', name: 'freemarker', version: '2.3.31'
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 读取控制台内容
|
||||
* </p>
|
||||
*/
|
||||
public static String scanner(String tip) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
StringBuilder help = new StringBuilder();
|
||||
help.append("请输入" + tip + ":");
|
||||
System.out.println(help.toString());
|
||||
if (scanner.hasNext()) {
|
||||
String ipt = scanner.next();
|
||||
if (StringUtils.isNotBlank(ipt)) {
|
||||
return ipt;
|
||||
}
|
||||
}
|
||||
throw new MybatisPlusException("请输入正确的" + tip + "!");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 代码生成器
|
||||
AutoGenerator mpg = new AutoGenerator();
|
||||
|
||||
// 全局配置
|
||||
GlobalConfig gc = new GlobalConfig();
|
||||
//获得当前文件路径
|
||||
String projectPath = System.getProperty("user.dir");
|
||||
gc.setOutputDir(projectPath + "/src/main/java");
|
||||
// gc.setOutputDir("D:\\test");
|
||||
gc.setAuthor("bozhiqiang");
|
||||
////是否打开资源管理器
|
||||
gc.setOpen(false);
|
||||
// gc.setSwagger2(true); 实体属性 Swagger2 注解
|
||||
//service接口:置生成的service接口名首字母是为I
|
||||
gc.setServiceName("%sService");
|
||||
mpg.setGlobalConfig(gc);
|
||||
|
||||
// 数据源配置
|
||||
DataSourceConfig dsc = new DataSourceConfig();
|
||||
dsc.setUrl("jdbc:mysql://110.42.251.214:3306/rindro?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC&allowPublicKeyRetrieval=true");
|
||||
// dsc.setSchemaName("public");
|
||||
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
|
||||
dsc.setUsername("root");
|
||||
dsc.setPassword("Yosin0102!");
|
||||
mpg.setDataSource(dsc);
|
||||
|
||||
// 包配置
|
||||
PackageConfig pc = new PackageConfig();
|
||||
pc.setModuleName(null);
|
||||
pc.setParent("com.example.zyk");
|
||||
//设置实体类包名 可不设 默认entity
|
||||
// pc.setEntity("entity");
|
||||
//设置mapper包名 可不设 默认 mapper
|
||||
// pc.setMapper("mapper");
|
||||
//设置service 包名 可不设默认 service
|
||||
// pc.setService("service");
|
||||
//设置controller 包名 可不设默认 controller
|
||||
// pc.setController("controller")
|
||||
mpg.setPackageInfo(pc);
|
||||
|
||||
// 自定义配置
|
||||
InjectionConfig cfg = new InjectionConfig() {
|
||||
@Override
|
||||
public void initMap() {
|
||||
// to do nothing
|
||||
}
|
||||
};
|
||||
|
||||
// 如果模板引擎是 freemarker
|
||||
String templatePath = "/templates/mapper.xml.ftl";
|
||||
// 如果模板引擎是 velocity
|
||||
// String templatePath = "/templates/mapper.xml.vm";
|
||||
|
||||
// 自定义输出配置
|
||||
List<FileOutConfig> focList = new ArrayList<>();
|
||||
// 自定义配置会被优先输出
|
||||
focList.add(new FileOutConfig(templatePath) {
|
||||
@Override
|
||||
public String outputFile(TableInfo tableInfo) {
|
||||
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
|
||||
return projectPath + "/src/main/resources/mapper/"
|
||||
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
|
||||
}
|
||||
});
|
||||
|
||||
cfg.setFileOutConfigList(focList);
|
||||
mpg.setCfg(cfg);
|
||||
|
||||
// 配置模板
|
||||
TemplateConfig templateConfig = new TemplateConfig();
|
||||
|
||||
templateConfig.setXml(null);
|
||||
mpg.setTemplate(templateConfig);
|
||||
|
||||
// 策略配置
|
||||
StrategyConfig strategy = new StrategyConfig();
|
||||
//表映射实体---去除表前缀
|
||||
strategy.setNaming(NamingStrategy.underline_to_camel);
|
||||
//字段映射实体---去除下划线
|
||||
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
|
||||
//实体类开启Lombok
|
||||
strategy.setEntityLombokModel(true);
|
||||
//控制层接口使用Rest
|
||||
strategy.setRestControllerStyle(true);
|
||||
//设置要映射的表名
|
||||
//String[] tableNames = {"表名1","表名2","","表名3","表名x"};
|
||||
//strategy.setInclude(tableNames);
|
||||
// strategy.setInclude("blog_tags","course","links","sys_settings","user_record"," user_say"); // 设置要映射的表名
|
||||
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
|
||||
strategy.setControllerMappingHyphenStyle(true);
|
||||
//去除表前缀
|
||||
strategy.setTablePrefix("m_");
|
||||
mpg.setStrategy(strategy);
|
||||
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
|
||||
mpg.execute();
|
||||
}
|
||||
}
|
||||
110
旧的java项目/src/main/java/com/example/sjkbf/SaticScheduleTask.java
Normal file
110
旧的java项目/src/main/java/com/example/sjkbf/SaticScheduleTask.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package com.example.sjkbf;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.LineHandler;
|
||||
import cn.hutool.core.io.file.Tailer;
|
||||
import cn.hutool.core.io.watch.SimpleWatcher;
|
||||
import cn.hutool.core.io.watch.WatchMonitor;
|
||||
import cn.hutool.core.io.watch.watchers.DelayWatcher;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.example.sjkbf.common.FileManage;
|
||||
import com.example.sjkbf.controller.AccountCargoController;
|
||||
import com.example.sjkbf.service.impl.ProjectPerServiceImpl;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.*;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.WatchEvent;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration //1.主要用于标记配置类,兼备Component的效果。
|
||||
@EnableScheduling // 2.开启定时任务
|
||||
public class SaticScheduleTask {
|
||||
@Autowired
|
||||
public ProjectPerServiceImpl projectPerService;
|
||||
|
||||
@Autowired
|
||||
FileManage fileManage;
|
||||
|
||||
private static ConfigurableApplicationContext context;
|
||||
//3.添加定时任务
|
||||
// @Scheduled(cron = "0 0 0/2 * * ?")
|
||||
@PostConstruct
|
||||
public void configureTasks() throws Exception {
|
||||
fileManage.init();
|
||||
|
||||
projectPerService.initInfo();
|
||||
|
||||
WatchMonitor all = WatchMonitor.createAll(fileManage.getScriptfile(), new DelayWatcher(new SimpleWatcher(){
|
||||
@Override
|
||||
public void onModify(WatchEvent<?> event, Path currentPath) {
|
||||
try {
|
||||
projectPerService.initInfo();
|
||||
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
StaticLog.error("重载项目配置文件出现异常");
|
||||
}
|
||||
System.out.println("重载配置文件");
|
||||
}
|
||||
}, 500));
|
||||
|
||||
all.setMaxDepth(4);
|
||||
all.start();
|
||||
|
||||
// Tailer tailer = new Tailer(FileUtil.file(fileManage.getConfigfile()), new LineHandler() {
|
||||
// @Override
|
||||
// public void handle(String s) {
|
||||
// try {
|
||||
// projectPerService.initInfo();
|
||||
//
|
||||
// }catch (Exception e){
|
||||
// e.printStackTrace();
|
||||
// StaticLog.error("重载项目配置文件出现异常");
|
||||
// }
|
||||
// System.out.println("重载配置文件");
|
||||
// }
|
||||
// }, 1);
|
||||
//
|
||||
// //新建一个线程
|
||||
// Thread thread = new Thread(
|
||||
// tailer::start
|
||||
// );
|
||||
// thread.start();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Autowired
|
||||
AccountCargoController cargoController;
|
||||
|
||||
// @Scheduled(cron = "0 0 1 * * ?")
|
||||
// private void configureTasks2(){
|
||||
// cargoController.save();
|
||||
// }
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(2620+1940+1450+741 - ((40+37 +94 +20)*2) -70);
|
||||
System.out.println(6299*0.7);
|
||||
System.out.println(4409-25-150-68-200-300-100-50+6+25-200-750-100-400-30-50+70+6-200-50);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.example.sjkbf;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
@SpringBootApplication()
|
||||
|
||||
public class SjkbfApplication {
|
||||
|
||||
private static ConfigurableApplicationContext context;
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
SpringApplication.run(SjkbfApplication.class, args);
|
||||
|
||||
|
||||
|
||||
// 添加自定义关闭钩子,打印触发源
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
||||
System.out.println("=====================================");
|
||||
System.out.println("=== 自定义ShutdownHook触发!开始定位原因 ===");
|
||||
System.out.println("触发时间:" + new java.util.Date());
|
||||
System.out.println("当前线程:" + Thread.currentThread().getName());
|
||||
// 打印所有线程的栈轨迹,找到触发关闭的源头
|
||||
Thread.getAllStackTraces().forEach((thread, stackTraces) -> {
|
||||
// 只打印关键线程(减少日志量)
|
||||
if (thread.getName().contains("ShutdownHook") || thread.getName().contains("main")
|
||||
|| thread.getName().contains("Task") || thread.getName().contains("Timer")) {
|
||||
System.out.println("\n线程名称:" + thread.getName() + " (状态:" + thread.getState() + ")");
|
||||
for (StackTraceElement elem : stackTraces) {
|
||||
System.out.println("\t" + elem);
|
||||
}
|
||||
}
|
||||
});
|
||||
System.out.println("=== ShutdownHook触发原因定位结束 ===");
|
||||
System.out.println("=====================================");
|
||||
|
||||
|
||||
System.out.println("=== 应用触发关闭,开始重启上下文 ===");
|
||||
// 关闭当前上下文
|
||||
context.close();
|
||||
// 重新启动上下文
|
||||
context = SpringApplication.run(SjkbfApplication.class, args);
|
||||
}, "Custom-Exit-Detector"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.example.sjkbf.common;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Data
|
||||
public class FileManage {
|
||||
|
||||
@Value("${pro.configfile}")
|
||||
private String configfile;
|
||||
|
||||
@Value("${pro.userfile}")
|
||||
private String file;
|
||||
|
||||
|
||||
@Value("${pro.filemap}")
|
||||
private String filemap;
|
||||
|
||||
@Value("${pro.scriptfile}")
|
||||
private String scriptfile;
|
||||
|
||||
@Value("${pro.dps}")
|
||||
private String dpsfile;
|
||||
|
||||
private String dpsScriptfile;
|
||||
|
||||
|
||||
public void init(){
|
||||
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.contains("win")) {
|
||||
dpsScriptfile = file +"dpsScript\\";
|
||||
}else {
|
||||
dpsScriptfile = file +"dpsScript/";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.example.sjkbf.config.Configuration;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CurrentUserId {
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.example.sjkbf.config.Configuration;
|
||||
|
||||
import com.example.sjkbf.entity.AuthUser;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
|
||||
resolvers.add(new CurrentUserIdResolver());
|
||||
}
|
||||
|
||||
public static class CurrentUserIdResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(CurrentUserId.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter,
|
||||
ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest,
|
||||
WebDataBinderFactory binderFactory) {
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String userName = (String)authentication.getPrincipal();
|
||||
return userName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.example.sjkbf.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
// 1. 创建 CORS 配置对象
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
|
||||
// 允许的域名(生产环境建议明确指定,而非使用通配符)
|
||||
config.addAllowedOriginPattern("*"); // Spring Boot 2.4+ 使用 allowedOriginPatterns
|
||||
// config.addAllowedOrigin("http://localhost:8080"); // 明确指定域名
|
||||
|
||||
// 允许的请求头
|
||||
config.addAllowedHeader("*");
|
||||
|
||||
// 允许的 HTTP 方法
|
||||
config.addAllowedMethod("GET");
|
||||
config.addAllowedMethod("POST");
|
||||
config.addAllowedMethod("PUT");
|
||||
config.addAllowedMethod("DELETE");
|
||||
config.addAllowedMethod("OPTIONS"); // 预检请求需要
|
||||
|
||||
// 是否允许发送 Cookie
|
||||
config.setAllowCredentials(true);
|
||||
|
||||
// 预检请求缓存时间(秒)
|
||||
config.setMaxAge(3600L);
|
||||
|
||||
// 2. 注册 CORS 配置应用到所有路径
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
|
||||
// 3. 返回 CORS 过滤器
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.example.sjkbf.config;
|
||||
|
||||
import com.example.sjkbf.util.JwtTokenUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
|
||||
// 1. 从请求头获取 Token
|
||||
String token = jwtTokenUtil.getTokenFromRequest(request);
|
||||
try {
|
||||
// 2. Token 存在且有效(基础验证:签名、过期时间)
|
||||
if (token != null && jwtTokenUtil.validateToken(token)) {
|
||||
// 3. 直接从 Token 中解析用户信息和权限(无需查库)
|
||||
String username = jwtTokenUtil.getUsernameFromToken(token);
|
||||
List<GrantedAuthority> authorities = jwtTokenUtil.getAuthoritiesFromToken(token)
|
||||
.stream()
|
||||
.map(SimpleGrantedAuthority ::new)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 4. 构建 Authentication 对象(权限来自 Token)
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
username, // 主体可以是用户名(或自定义 User 对象)
|
||||
null, // 凭证(密码)无需存储
|
||||
authorities
|
||||
);
|
||||
|
||||
// 5. 存入 SecurityContext(后续鉴权直接使用 Token 中的权限)
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}catch (JwtException e){
|
||||
sendErrorResponse(response, 4011, "请重新登录");
|
||||
return;
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Token 解析失败(如篡改、过期),清理上下文
|
||||
SecurityContextHolder.clearContext();
|
||||
sendErrorResponse(response, 4013, "认证失败");
|
||||
logger.error("认证失败:" + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// 6. 继续过滤器链
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
// 发送 JSON 错误响应
|
||||
private void sendErrorResponse(HttpServletResponse response, int code, String message)
|
||||
throws IOException {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
|
||||
Map<String, Object> errorData = new HashMap<>();
|
||||
errorData.put("code", code);
|
||||
errorData.put("msg", message);
|
||||
|
||||
response.getWriter().write(new ObjectMapper().writeValueAsString(errorData));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.sjkbf.config;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
// 插入时自动填充创建时间
|
||||
this.strictInsertFill(metaObject, "createTime", Date.class, DateUtil.date());
|
||||
// 插入时自动填充更新时间
|
||||
this.strictInsertFill(metaObject, "updateTime", Date.class, DateUtil.date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
// 更新时自动填充更新时间
|
||||
this.strictUpdateFill(metaObject, "updateTime", Date.class, DateUtil.date());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.example.sjkbf.config;
|
||||
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class RateLimitConfig {
|
||||
// 总带宽限制:15MB/s = 15 * 1024 * 1024 B/s
|
||||
private static final double TOTAL_BANDWIDTH = 15 * 1024 * 1024;
|
||||
|
||||
@Bean
|
||||
public RateLimiter globalRateLimiter() {
|
||||
return RateLimiter.create(TOTAL_BANDWIDTH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.example.sjkbf.config;
|
||||
|
||||
import com.example.sjkbf.config.exception.CustomAuthenticationEntryPoint;
|
||||
import com.example.sjkbf.service.impl.UserDetailsServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* Spring Security 核心配置类
|
||||
* - 继承 WebSecurityConfigurerAdapter(适配 Spring Boot 2.5.x)
|
||||
* - 启用方法级权限控制(@PreAuthorize)
|
||||
* - 配置 JWT 过滤器、密码加密、认证规则等
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true) // 启用方法级权限注解
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private UserDetailsServiceImpl userDetailsService; // 用户服务(需自行实现)
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; // JWT 过滤器
|
||||
|
||||
@Autowired
|
||||
private CorsFilter corsFilter; // 跨域过滤器(需自行配置)
|
||||
|
||||
// 认证失败处理器
|
||||
@Autowired
|
||||
private CustomAuthenticationEntryPoint unauthorizedHandler;
|
||||
|
||||
|
||||
// @Autowired
|
||||
// private LogoutSuccessHandlerImpl logoutSuccessHandler; // 注销成功处理器
|
||||
|
||||
/**
|
||||
* 密码加密器(强制使用 BCrypt)
|
||||
*/
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证管理器(暴露为 Bean,供登录接口调用)
|
||||
*/
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置用户认证来源(如数据库)
|
||||
*/
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
//注册验证用户的处理器 和密码加密器
|
||||
auth.userDetailsService(userDetailsService)
|
||||
.passwordEncoder(passwordEncoder());
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心安全配置
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
// ==================== 基础配置 ====================
|
||||
.csrf().disable() // 关闭 CSRF(REST API 无状态,无需 CSRF)
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 无状态会话
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(unauthorizedHandler) // 认证失败处理(如未登录访问受保护接口)
|
||||
.accessDeniedHandler(new AccessDeniedHandlerImpl()) // 权限不足处理(已登录但无权限)
|
||||
.and()
|
||||
|
||||
// ==================== 授权规则 ====================
|
||||
.authorizeRequests()
|
||||
// 开放接口(无需认证)
|
||||
.antMatchers(
|
||||
"/login",
|
||||
"/register",
|
||||
"/changePassword",
|
||||
"/dps/*",
|
||||
"/dps/*/*",
|
||||
"/rindro/download",
|
||||
"/rindro/download/*",
|
||||
"/rindro/mp4",
|
||||
"/rindro/getversion",
|
||||
"/rindro/addgold",
|
||||
"/rindro/getimg/*/*",
|
||||
"/rindro/getthumb/*/*",
|
||||
|
||||
"/rindro/getmp4/*/*",
|
||||
"/rindro/getmp42/*/*",
|
||||
"/script/*",
|
||||
"/api/videos/*/*",
|
||||
"/zf/callback",
|
||||
"/rindro/download/*/*"
|
||||
).permitAll()
|
||||
// 其他所有请求需认证
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
|
||||
// ==================== 过滤器配置 ====================
|
||||
|
||||
// 添加 CORS 过滤器在最前
|
||||
.addFilterBefore(corsFilter, LogoutFilter.class)
|
||||
// 添加 JWT 过滤器在登录认证过滤器之前
|
||||
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
|
||||
// ==================== 注销配置 ====================
|
||||
// .logout()
|
||||
// .logoutUrl("/logout") // 注销接口
|
||||
// .logoutSuccessHandler(logoutSuccessHandler) // 注销成功处理(返回 JSON)
|
||||
// .deleteCookies("JSESSIONID"); // 删除 Cookie(如果使用)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.example.sjkbf.config;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.sjkbf.controller.AccountCargoController;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Date;
|
||||
|
||||
@Configuration //1.主要用于标记配置类,兼备Component的效果。
|
||||
@EnableScheduling // 2.开启定时任务
|
||||
public class StartInit {
|
||||
|
||||
|
||||
@Scheduled(cron = "0 0 0 * * ?")
|
||||
public void configureTasks() throws Exception {
|
||||
AccountCargoController.a.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.example.sjkbf.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.web.servlet.config.annotation.*;
|
||||
import org.springframework.web.servlet.resource.EncodedResourceResolver;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Configuration
|
||||
public class VideoConfig implements WebMvcConfigurer {
|
||||
|
||||
/**
|
||||
* 配置视频文件缓存策略
|
||||
*/
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// 1. 转码视频资源映射(/tmp/video-transcoded/)
|
||||
registry.addResourceHandler("/transcoded/**")
|
||||
.addResourceLocations("file:/tmp/video-transcoded/")
|
||||
.setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
|
||||
.resourceChain(true)
|
||||
.addResolver(new EncodedResourceResolver());
|
||||
|
||||
// 2. 原始视频资源映射(/root/rindro/Script/Project/)
|
||||
registry.addResourceHandler("/original/**")
|
||||
.addResourceLocations("file:/root/rindro/Script/Project/")
|
||||
.setCacheControl(CacheControl.noCache())
|
||||
.resourceChain(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.example.sjkbf.config.exception;
|
||||
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Component
|
||||
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
|
||||
throws IOException {
|
||||
// 默认处理,实际应由全局异常处理器接管
|
||||
// 设置响应状态码和内容类型
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
|
||||
// 构建自定义错误信息
|
||||
Map<String, Object> errorData = new HashMap<>();
|
||||
errorData.put("code", 4010);
|
||||
errorData.put("msg", "此页面需要登录后访问");
|
||||
|
||||
// 写入 JSON 响应
|
||||
response.getWriter().write(new ObjectMapper().writeValueAsString(errorData));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.example.sjkbf.config.exception;
|
||||
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.example.sjkbf.entity.CommonResult;
|
||||
|
||||
import org.apache.catalina.connector.ClientAbortException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
|
||||
|
||||
// 处理用户名密码错误异常(Spring Security 默认抛出 BadCredentialsException)
|
||||
@ExceptionHandler(BadCredentialsException.class)
|
||||
public ResponseEntity<?> handleBadCredentials(BadCredentialsException e) {
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("msg", "用户名或密码错误");
|
||||
response.put("code", 4010);
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||
.body(response);
|
||||
}
|
||||
|
||||
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
public ResponseEntity<CommonResult<String>> responseEntity(RuntimeException e) {
|
||||
|
||||
e.printStackTrace();
|
||||
return ResponseEntity.status(HttpStatus.CREATED)
|
||||
.body(CommonResult.failed(201,e.getMessage()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理视频文件不存在异常
|
||||
*/
|
||||
@ExceptionHandler(FileNotFoundException.class)
|
||||
public ResponseEntity<String> handleFileNotFound(FileNotFoundException e) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body("Video file not found: " + e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理转码异常
|
||||
*/
|
||||
@ExceptionHandler(IOException.class)
|
||||
public ResponseEntity<String> handleTranscodeError(IOException e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Video processing error: " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
@ExceptionHandler(ClientAbortException.class)
|
||||
public void handleClientAbortException(ClientAbortException e) {
|
||||
// 仅打印警告日志,无需向上抛出
|
||||
StaticLog.info("客户端主动断开连接: {}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
package com.example.sjkbf.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.example.sjkbf.common.FileManage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* InnoDB free: 11264 kB 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2022-04-03
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/dps")
|
||||
public class AccountCargoController {
|
||||
|
||||
@Autowired
|
||||
FileManage fileManage;
|
||||
|
||||
public static Map<String,Integer> a=new HashMap<>();
|
||||
|
||||
@RequestMapping("/login")
|
||||
public int login(HttpServletRequest request) {
|
||||
|
||||
String ipAddress = getIpAddress(request);
|
||||
a.put(ipAddress,a.size()+1);
|
||||
return a.size();
|
||||
}
|
||||
|
||||
@RequestMapping("/getversion")
|
||||
public String getversion() {
|
||||
|
||||
FileReader fileReader = new FileReader(fileManage.getDpsfile()+"Application/Proj.ifo");
|
||||
String result = fileReader.readString();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/getclientversion")
|
||||
public String getclientversion() {
|
||||
|
||||
FileReader fileReader = new FileReader(fileManage.getDpsfile()+"Marketplace/Proj.ifo");
|
||||
String result = fileReader.readString();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping("/getlist")
|
||||
public String getlist() {
|
||||
|
||||
|
||||
File[] ls = FileUtil.ls(fileManage.getDpsfile()+"Script");
|
||||
|
||||
StringBuilder list = new StringBuilder("{ \"list\":[");
|
||||
for (File l : ls) {
|
||||
FileReader fileReader = new FileReader(l+"/"+"Proj.ifo");
|
||||
|
||||
list.append(fileReader.readString()).append(",");
|
||||
}
|
||||
list.deleteCharAt(list.length() - 1);
|
||||
list.append("]}");
|
||||
return list.toString();
|
||||
}
|
||||
|
||||
@RequestMapping("/getadvertisement")
|
||||
public String getadvertisement() {
|
||||
|
||||
|
||||
File[] ls = FileUtil.ls(fileManage.getDpsfile()+"Advertisement");
|
||||
//按文件夹名字排序
|
||||
Arrays.sort(ls, Comparator.comparing(File::getName));
|
||||
StringBuilder list = new StringBuilder("{ \"list\":[");
|
||||
for (File l : ls) {
|
||||
FileReader fileReader = new FileReader(l+"/"+"info.ifo");
|
||||
|
||||
list.append(fileReader.readString()).append(",");
|
||||
}
|
||||
list.deleteCharAt(list.length() - 1);
|
||||
list.append("]}");
|
||||
return list.toString();
|
||||
}
|
||||
|
||||
// 使用正则表达式捕获所有字符(包括斜杠)
|
||||
@PostMapping("/download/{colonPath}")
|
||||
public ResponseEntity<Resource> download(
|
||||
@PathVariable String colonPath) throws Exception {
|
||||
|
||||
// 1. 解码中文路径
|
||||
String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
// System.out.println("接收到参数: " + decodedPath);
|
||||
|
||||
// 2. 将冒号还原为斜杠
|
||||
String realPath = decodedPath.replace(":", "/");
|
||||
// System.out.println("真实路径: " + realPath);
|
||||
StaticLog.info( "文件下载1: " + realPath );
|
||||
// 3. 构建绝对路径
|
||||
Path baseDir = Paths.get(fileManage.getDpsfile()+"Script").toAbsolutePath().normalize();
|
||||
Path targetPath = baseDir.resolve(realPath).normalize();
|
||||
|
||||
// 4. 安全校验(防止路径穿越)
|
||||
if (!targetPath.startsWith(baseDir)) {
|
||||
System.err.println("非法路径尝试: " + realPath);
|
||||
return ResponseEntity.status(403).build();
|
||||
}
|
||||
|
||||
// 5. 返回文件
|
||||
Resource resource = new FileSystemResource(targetPath);
|
||||
if (!resource.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Disposition",
|
||||
"attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
|
||||
// 使用正则表达式捕获所有字符(包括斜杠)
|
||||
@PostMapping ("/download2/{colonPath}")
|
||||
public ResponseEntity<Resource> download2(
|
||||
@PathVariable String colonPath) throws Exception {
|
||||
|
||||
// 1. 解码中文路径
|
||||
String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
// System.out.println("接收到参数: " + decodedPath);
|
||||
|
||||
// 2. 将冒号还原为斜杠
|
||||
String realPath = decodedPath.replace(":", "/");
|
||||
// System.out.println("真实路径: " + realPath);
|
||||
// 3. 构建绝对路径
|
||||
Path baseDir = Paths.get(fileManage.getDpsfile()+"Application").toAbsolutePath().normalize();
|
||||
Path targetPath = baseDir.resolve(realPath).normalize();
|
||||
|
||||
// 4. 安全校验(防止路径穿越)
|
||||
if (!targetPath.startsWith(baseDir)) {
|
||||
System.err.println("非法路径尝试: " + realPath);
|
||||
return ResponseEntity.status(403).build();
|
||||
}
|
||||
|
||||
// 5. 返回文件
|
||||
Resource resource = new FileSystemResource(targetPath);
|
||||
if (!resource.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Disposition",
|
||||
"attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
@RequestMapping("/download3/{colonPath}")
|
||||
public ResponseEntity<Resource> download3(
|
||||
@PathVariable String colonPath) throws Exception {
|
||||
|
||||
// 1. 解码中文路径
|
||||
String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
// System.out.println("接收到参数: " + decodedPath);
|
||||
|
||||
// 2. 将冒号还原为斜杠
|
||||
String realPath = decodedPath.replace(":", "/");
|
||||
// System.out.println("真实路径: " + realPath);
|
||||
|
||||
// 3. 构建绝对路径
|
||||
Path baseDir = Paths.get(fileManage.getDpsfile()+"Advertisement").toAbsolutePath().normalize();
|
||||
Path targetPath = baseDir.resolve(realPath).normalize();
|
||||
|
||||
// 4. 安全校验(防止路径穿越)
|
||||
if (!targetPath.startsWith(baseDir)) {
|
||||
System.err.println("非法路径尝试: " + realPath);
|
||||
return ResponseEntity.status(403).build();
|
||||
}
|
||||
|
||||
// 5. 返回文件
|
||||
Resource resource = new FileSystemResource(targetPath);
|
||||
if (!resource.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Disposition",
|
||||
"attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
File[] ls = FileUtil.ls("C:\\Users\\12134\\Downloads\\Advertisement");
|
||||
|
||||
StringBuilder list = new StringBuilder("{ \"list\":[");
|
||||
for (File l : ls) {
|
||||
FileReader fileReader = new FileReader(l+"\\"+"info.ifo");
|
||||
|
||||
list.append(fileReader.readString()).append(",");
|
||||
}
|
||||
list.deleteCharAt(list.length() - 1);
|
||||
list.append("]}");
|
||||
|
||||
System.out.println(list.toString());
|
||||
}
|
||||
|
||||
//添加
|
||||
public static String processCommand(String input) {
|
||||
// 按行处理以保留格式
|
||||
String[] lines = input.split("\n");
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
for (String line : lines) {
|
||||
// 处理包含df_game_r的命令行(包括注释行)
|
||||
if (line.contains("./df_game_r siroco")) {
|
||||
line = processGameLine(line);
|
||||
}
|
||||
|
||||
result.append(line).append("\n");
|
||||
}
|
||||
|
||||
return result.toString().trim();
|
||||
}
|
||||
|
||||
private static String processGameLine(String line) {
|
||||
// 检查是否是注释行
|
||||
boolean isCommented = line.trim().startsWith("#");
|
||||
String workingLine = isCommented ? line.substring(line.indexOf("#") + 1) : line;
|
||||
|
||||
// 检查是否已有LD_PRELOAD
|
||||
Matcher preloadMatcher = Pattern.compile("LD_PRELOAD\\s*=\\s*\"([^\"]*)\"").matcher(workingLine);
|
||||
|
||||
if (preloadMatcher.find()) {
|
||||
// 已有LD_PRELOAD的情况:确保包含目标库
|
||||
String libs = preloadMatcher.group(1).trim();
|
||||
if (!libs.contains("/dp_s/lib/libAurora.so")) {
|
||||
String newLibs = "/dp_s/lib/libAurora.so" + (libs.isEmpty() ? "" : " " + libs);
|
||||
workingLine = workingLine.replaceFirst("LD_PRELOAD\\s*=\\s*\"[^\"]*\"",
|
||||
"LD_PRELOAD=\" " + newLibs + "\"");
|
||||
}
|
||||
} else {
|
||||
// 没有LD_PRELOAD的情况:添加
|
||||
workingLine = workingLine.replaceFirst("(\\./df_game_r\\s+siroco)",
|
||||
"LD_PRELOAD=\" /dp_s/lib/libAurora.so\" $1");
|
||||
}
|
||||
|
||||
return isCommented ? "#" + workingLine : workingLine;
|
||||
}
|
||||
|
||||
//删除
|
||||
public static String cleanLdPreload(String input) {
|
||||
// 使用Matcher的region功能保留所有换行符
|
||||
StringBuilder result = new StringBuilder();
|
||||
Pattern pattern = Pattern.compile(
|
||||
"(LD_PRELOAD\\s*=\\s*\")([^\"]*?)/dp_s/lib/libAurora\\.so([^\"]*?)(\")|" +
|
||||
"(LD_PRELOAD\\s*=\\s*\"\\s*\")"
|
||||
);
|
||||
|
||||
Matcher matcher = pattern.matcher(input);
|
||||
int lastPos = 0;
|
||||
|
||||
while (matcher.find()) {
|
||||
// 添加匹配前的内容(包含所有换行符)
|
||||
result.append(input, lastPos, matcher.start());
|
||||
|
||||
// 处理匹配到的内容
|
||||
if (matcher.group(1) != null) { // 情况1:包含Aurora.so
|
||||
String replacement = matcher.group(1) +
|
||||
matcher.group(2) +
|
||||
matcher.group(3) +
|
||||
matcher.group(4);
|
||||
// 如果替换后变成LD_PRELOAD="",则完全删除
|
||||
if (replacement.equals("LD_PRELOAD=\"\"")) {
|
||||
// 不添加任何内容(相当于删除)
|
||||
} else {
|
||||
result.append(replacement);
|
||||
}
|
||||
} else { // 情况2:空的LD_PRELOAD
|
||||
// 完全跳过不添加(删除)
|
||||
}
|
||||
|
||||
lastPos = matcher.end();
|
||||
}
|
||||
|
||||
// 添加剩余内容
|
||||
result.append(input.substring(lastPos));
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static String getIpAddress(HttpServletRequest request) {
|
||||
// 获取请求的IP地址
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
// 如果应用部署在反向代理或负载均衡器后面,可以通过X-Forwarded-For头部获取真实IP地址
|
||||
String forwardedFor = request.getHeader("X-Forwarded-For");
|
||||
if (forwardedFor != null && !forwardedFor.isEmpty()) {
|
||||
ipAddress = forwardedFor.split(",")[0];
|
||||
}
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.example.sjkbf.controller;
|
||||
|
||||
import com.example.sjkbf.entity.CommonResult;
|
||||
import com.example.sjkbf.entity.DTO.LoginRequest;
|
||||
import com.example.sjkbf.entity.DTO.LoginResponse;
|
||||
import com.example.sjkbf.service.UserService;
|
||||
import com.example.sjkbf.util.JwtTokenUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
public class AuthController {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtil jwtTokenUtil;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<?> login(@Valid @RequestBody LoginRequest request) {
|
||||
// 1. 创建认证令牌(未认证状态)
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword());
|
||||
|
||||
// 2. 执行认证(Spring Security 自动调用 UserDetailsService)
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
|
||||
// 3. 认证成功,生成 JWT
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
String token = jwtTokenUtil.generateToken(userDetails);
|
||||
|
||||
// 4. 提取权限信息
|
||||
List<String> roles = userDetails.getAuthorities().stream()
|
||||
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 5. 返回响应
|
||||
return ResponseEntity.ok(
|
||||
new LoginResponse("Bearer "+token, userDetails.getUsername(), roles)
|
||||
);
|
||||
}
|
||||
|
||||
// 用户注册接口
|
||||
@PostMapping("/register")
|
||||
public ResponseEntity<CommonResult<String>> register(@Valid @RequestBody LoginRequest request) {
|
||||
if (request.getUsername()==null|| request.getUsername().isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(CommonResult.failed(201,"用户名为空"));
|
||||
}
|
||||
if (request.getPassword()==null|| request.getPassword().isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(CommonResult.failed(201,"密码为空"));
|
||||
}
|
||||
if (request.getQq()==null|| request.getQq().isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(CommonResult.failed(201,"安全口令为空"));
|
||||
}
|
||||
|
||||
// 检查用户名是否已存在
|
||||
if (userService.isUsernameExist(request.getUsername())) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(CommonResult.failed(201,"用户名已存在"));
|
||||
}
|
||||
|
||||
|
||||
// 保存用户
|
||||
userService.registerUser(request);
|
||||
return ResponseEntity.ok(CommonResult.success("注册成功"));
|
||||
}
|
||||
|
||||
//找回密码
|
||||
@PostMapping("/changePassword")
|
||||
public ResponseEntity<CommonResult<String>> changePassword(@Valid @RequestBody LoginRequest request) {
|
||||
if (request.getUsername()==null|| request.getUsername().isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(CommonResult.failed(201,"用户名为空"));
|
||||
}
|
||||
if (request.getPassword()==null|| request.getPassword().isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(CommonResult.failed(201,"密码为空"));
|
||||
}
|
||||
if (request.getQq()==null|| request.getQq().isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(CommonResult.failed(201,"安全口令为空"));
|
||||
}
|
||||
|
||||
// 保存用户
|
||||
userService.updatePassword(request);
|
||||
return ResponseEntity.ok(CommonResult.success("修改成功"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,699 @@
|
||||
package com.example.sjkbf.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.sjkbf.common.FileManage;
|
||||
import com.example.sjkbf.config.Configuration.CurrentUserId;
|
||||
import com.example.sjkbf.entity.*;
|
||||
import com.example.sjkbf.entity.projectconfig.Project;
|
||||
import com.example.sjkbf.service.ProjectPerService;
|
||||
import com.example.sjkbf.service.UserAndServerService;
|
||||
import com.example.sjkbf.service.UserServerProjectService;
|
||||
import com.example.sjkbf.service.UserService;
|
||||
import com.google.common.util.concurrent.RateLimiter;
|
||||
import net.coobird.thumbnailator.Thumbnails;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.*;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/rindro")
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private ProjectPerService projectPerService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserAndServerService userAndServerService;
|
||||
|
||||
@Autowired
|
||||
private UserServerProjectService userServerProjectService;
|
||||
|
||||
@Autowired
|
||||
FileManage fileManage;
|
||||
|
||||
|
||||
//下载插件相关内容
|
||||
@PostMapping("/download")
|
||||
public ResponseEntity<Object> download(@RequestBody Map<String,String> body) throws Exception {
|
||||
// //如果不是通用文件就要先检查
|
||||
// if (!body.get("projectName").contains("通用")) {
|
||||
// List<UserServerProject> byUserName = userServerProjectService.getByUserName(userName);
|
||||
// if (byUserName == null) {
|
||||
// // 若服务器没有该插件,返回错误信息的通用结果
|
||||
// return new ResponseEntity<>(CommonResult.failed("没有插件授权 无法下载相关内容"), HttpStatus.OK);
|
||||
// }
|
||||
// for (UserServerProject userServerProject : byUserName) {
|
||||
// boolean isExpired = false;
|
||||
// if (userServerProject.getProjectName().equals(body.get("projectName"))) {
|
||||
// isExpired =true;
|
||||
// }
|
||||
// if (!isExpired){
|
||||
// return new ResponseEntity<>(CommonResult.failed("没有插件授权 无法下载相关内容"), HttpStatus.OK);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
String file = "/root/rindro/download/profile/"+body.get("projectName")+".zip";
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.contains("win")) {
|
||||
file = "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\download\\profile\\"+body.get("projectName")+".zip";
|
||||
}
|
||||
|
||||
Path baseDir = Paths.get(file).toAbsolutePath().normalize();
|
||||
Resource resource = new FileSystemResource(baseDir);
|
||||
|
||||
// 设置响应头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"");
|
||||
|
||||
// 返回包含文件资源的通用结果
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Disposition",
|
||||
"attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//获得账号信息
|
||||
@PostMapping("/getInfo")
|
||||
public ResponseEntity<CommonResult<Map<String,Object>>> getInfo(@CurrentUserId String userName) {
|
||||
User user = userService.getOne(new QueryWrapper<User>().eq("username", userName));
|
||||
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("userpoints", user.getGold());
|
||||
body.put("username", user.getName());
|
||||
body.put("useravatar", user.getImg());
|
||||
body.put("uservip", "普通会员");
|
||||
body.put("usercash", null);
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(body));
|
||||
}
|
||||
|
||||
//
|
||||
// /**
|
||||
// * 获得项目的标题文件
|
||||
// * @param colonPath
|
||||
// * @return
|
||||
// * @throws UnsupportedEncodingException
|
||||
// */
|
||||
// @RequestMapping("/getimg/{colonPath}")
|
||||
// public ResponseEntity<Resource> getimg(@PathVariable String colonPath) throws UnsupportedEncodingException {
|
||||
// String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
//
|
||||
// Project byName = projectPerService.getByName(decodedPath);
|
||||
// if (byName==null)return null;
|
||||
// String imgPath = byName.getImgPath();
|
||||
//
|
||||
// String file = "/root/rindro/Script/"+imgPath;
|
||||
// String os = System.getProperty("os.name").toLowerCase();
|
||||
// if (os.contains("win")) {
|
||||
// file = "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\Script\\"+imgPath;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // 5. 返回文件
|
||||
// Resource resource = new FileSystemResource(file);
|
||||
// if (!resource.exists()) {
|
||||
// return ResponseEntity.notFound().build();
|
||||
// }
|
||||
//
|
||||
// return ResponseEntity.ok()
|
||||
// .header("Content-Disposition",
|
||||
// "attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
// .body(resource);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获得项目文件中的图片
|
||||
* @param colonPath
|
||||
* @return
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
@RequestMapping("/getimg/{colonPath}/{img}")
|
||||
public ResponseEntity<Resource> getimg2(@PathVariable String colonPath,@PathVariable String img) throws UnsupportedEncodingException {
|
||||
String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
img = URLDecoder.decode(img, "UTF-8");
|
||||
|
||||
Project byName = projectPerService.getByName(decodedPath);
|
||||
|
||||
if (byName==null)return null;
|
||||
String imgPath = byName.getImgPath();
|
||||
|
||||
String file = "/root/rindro/Script/Project/"+imgPath+"/img/"+img+".png";
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.contains("win")) {
|
||||
file = "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\Script\\Project\\"+imgPath+"\\img\\"+img+".png";
|
||||
}
|
||||
// 5. 返回文件
|
||||
Resource resource = new FileSystemResource(file);
|
||||
if (!resource.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Disposition",
|
||||
"attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得项目文件中的缩略图(使用Thumbnailator)
|
||||
*/
|
||||
@RequestMapping("/getthumb/{colonPath}/{img}")
|
||||
public ResponseEntity<Resource> getThumbnailWithLib(
|
||||
@PathVariable String colonPath,
|
||||
@PathVariable String img,
|
||||
@RequestParam(required = false, defaultValue = "200") int width,
|
||||
@RequestParam(required = false, defaultValue = "200") int height)
|
||||
throws UnsupportedEncodingException, IOException {
|
||||
|
||||
String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
img = URLDecoder.decode(img, "UTF-8");
|
||||
|
||||
Project byName = projectPerService.getByName(decodedPath);
|
||||
if (byName == null) return ResponseEntity.notFound().build();
|
||||
|
||||
String imgPath = byName.getImgPath();
|
||||
String originalFile = "/root/rindro/Script/Project/" + imgPath + "/img/" + img + ".png";
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.contains("win")) {
|
||||
originalFile = "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\Script\\Project\\" + imgPath + "\\img\\" + img + ".png";
|
||||
}
|
||||
|
||||
// 检查原图是否存在
|
||||
Resource originalResource = new FileSystemResource(originalFile);
|
||||
if (!originalResource.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
// 使用Thumbnailator生成缩略图
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
|
||||
Thumbnails.of(originalFile)
|
||||
.size(width, height)
|
||||
.outputFormat("png")
|
||||
.outputQuality(0.8) // 设置输出质量
|
||||
.toOutputStream(outputStream);
|
||||
|
||||
byte[] thumbnailBytes = outputStream.toByteArray();
|
||||
ByteArrayResource resource = new ByteArrayResource(thumbnailBytes);
|
||||
|
||||
String downloadFileName = img + "_thumb_" + width + "x" + height + ".png";
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Type", "image/png")
|
||||
.header("Content-Disposition", "attachment; filename=\"" + downloadFileName + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得项目文件中的MP4
|
||||
* @param colonPath
|
||||
* @return
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
@RequestMapping("/getmp42/{colonPath}/{img}")
|
||||
public ResponseEntity<Resource> getmp4(@PathVariable String colonPath,@PathVariable String img) throws IOException {
|
||||
String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
img = URLDecoder.decode(img, "UTF-8");
|
||||
|
||||
Project byName = projectPerService.getByName(decodedPath);
|
||||
|
||||
if (byName==null)return null;
|
||||
String imgPath = byName.getImgPath();
|
||||
|
||||
String file = "/root/rindro/Script/Project/"+imgPath+"/vid/"+img+".mp4";
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.contains("win")) {
|
||||
file = "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\Script\\Project\\"+imgPath+"\\vid\\"+img+".mp4";
|
||||
}
|
||||
// 5. 返回文件
|
||||
Resource resource = new FileSystemResource(file);
|
||||
if (!resource.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Type", "video/mp4")
|
||||
// 添加下行强制变为下载行为(与Alist一致)
|
||||
.header("Content-Disposition", "attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.header("Accept-Ranges", "bytes")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
|
||||
//购买
|
||||
@PostMapping("/buy")
|
||||
public ResponseEntity<CommonResult<Object>> buy( @RequestBody Map<String,String> body,@CurrentUserId String userName) throws Exception {
|
||||
|
||||
|
||||
String buy = userService.buy(body.get("ip"), body.get("projectName"), userName);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("info",buy);
|
||||
if (buy.equals("购买成功")){
|
||||
UserServerProject byIPAndName = userServerProjectService.getByIPAndName(body.get("ip"), body.get("projectName"));
|
||||
DateTime date = DateUtil.date(byIPAndName.getExpirationDate());
|
||||
|
||||
String format = DateUtil.format(date, "yyyy-MM-dd");
|
||||
result.put("endTime",format);
|
||||
return ResponseEntity.ok(CommonResult.success(result));
|
||||
}
|
||||
|
||||
|
||||
return ResponseEntity.ok(CommonResult.failed(buy));
|
||||
}
|
||||
|
||||
//充值
|
||||
@GetMapping("/addgold")
|
||||
public ResponseEntity<CommonResult<String>> addgold(String userName,Integer gold){
|
||||
String addgold = userService.addgold(userName,gold);
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(addgold));
|
||||
}
|
||||
//转让
|
||||
@PostMapping("/transfer")
|
||||
public ResponseEntity<CommonResult<String>> transfer(@RequestBody Map<String,String> body,@CurrentUserId String userName){
|
||||
String transfer = userService.transfer(userName,body.get("username"), Integer.valueOf(body.get("gold")));
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(transfer));
|
||||
}
|
||||
|
||||
|
||||
//给账号添加服务器
|
||||
@PostMapping("/addServer")
|
||||
public ResponseEntity<CommonResult<String>> addServer(@RequestBody Map<String,String> body,@CurrentUserId String userName){
|
||||
String addServer = userService.addServer(body.get("ip"),userName,body.get("username"),body.get("password"),body.get("port"));
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(addServer));
|
||||
}
|
||||
//给账号删除服务器
|
||||
@PostMapping("/deleteServer")
|
||||
public ResponseEntity<CommonResult<String>> deleteServer(@RequestBody Map<String,String> body,@CurrentUserId String userName){
|
||||
String deleteServer = userService.deleteServer(body.get("ip"), userName);
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(deleteServer));
|
||||
}
|
||||
//获得服务器列表
|
||||
@PostMapping("/getServerList")
|
||||
public ResponseEntity<CommonResult<List<Map<String,Object>>>> getServerList(@CurrentUserId String userName){
|
||||
List<UserAndServer> serverList = userAndServerService.getServerList(userName);
|
||||
// List<String> collect = serverList.stream().map(UserAndServer::getServerIp).collect(Collectors.toList());
|
||||
List<Map<String, Object> > body = serverList.stream().map(item -> {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("serverIp", item.getServerIp());
|
||||
map.put("userName", item.getAccount());
|
||||
map.put("password", item.getPassword());
|
||||
map.put("port", item.getPort());
|
||||
return map;
|
||||
}
|
||||
).collect(Collectors.toList());
|
||||
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(body));
|
||||
}
|
||||
|
||||
//获得服务器信息
|
||||
@PostMapping("/getServer")
|
||||
public ResponseEntity<CommonResult<UserAndServer>> getServer(@RequestBody Map<String,String> body,@CurrentUserId String userName){
|
||||
|
||||
UserAndServer userAndServer = userAndServerService.getOne(new QueryWrapper<UserAndServer>().eq("user_name", userName).eq("server_ip", body.get("ip")));
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(userAndServer));
|
||||
}
|
||||
|
||||
//获取插件信息
|
||||
@PostMapping("/getProjectInfoList")
|
||||
public ResponseEntity<CommonResult<Object>> getProjectInfoList(){
|
||||
Map<String, Map<String, Object>> body = projectPerService.getProjectInfoList();
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(body));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自己拥有的插件信息
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/getUserProList")
|
||||
public ResponseEntity<CommonResult<Object>> getgetUserProList(@RequestBody Map<String,String> body) {
|
||||
List<UserServerProject> byUserName = userServerProjectService.getpro(body.get("ip"));
|
||||
Map<String, Map<String, Object>> body2 = projectPerService.getProjectInfoListAll();
|
||||
|
||||
Map<String, Map<String, Object>> re =new HashMap<>();
|
||||
for (UserServerProject userServerProject : byUserName) {
|
||||
Map<String, Object> objectMap = body2.get(userServerProject.getProjectName());
|
||||
DateTime date = DateUtil.date(userServerProject.getExpirationDate());
|
||||
|
||||
String format = DateUtil.format(date, "yyyy-MM-dd");
|
||||
objectMap.put("endTime",format);
|
||||
objectMap.put("open",userServerProject.getOpen());
|
||||
re.put(userServerProject.getProjectName(),objectMap);
|
||||
}
|
||||
return ResponseEntity.ok(CommonResult.success(re));
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/download/sh")
|
||||
public ResponseEntity<Resource> downloadFileSh() {
|
||||
// 构建文件的完整路径
|
||||
File file = new File(fileManage.getFile()+"re.sh");
|
||||
|
||||
StaticLog.info("请求下载sh脚本"+file);
|
||||
if (!file.exists()) {
|
||||
// 如果文件不存在,返回 404 错误
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
// 创建文件资源对象
|
||||
Resource resource = new FileSystemResource(file);
|
||||
|
||||
// 设置响应头,告知浏览器这是一个附件,需要下载
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + "re.sh");
|
||||
|
||||
// 返回响应实体,包含文件资源、响应头和状态码
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.contentLength(file.length())
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
@GetMapping("/download/c")
|
||||
public ResponseEntity<Resource> downloadFileC() {
|
||||
// 构建文件的完整路径
|
||||
return getResourceResponseEntity("download/ndpsm_svr", "ndpsm_svr");
|
||||
}
|
||||
|
||||
@GetMapping("/download/d")
|
||||
public ResponseEntity<Resource> downloadFileD() {
|
||||
// 构建文件的完整路径
|
||||
return getResourceResponseEntity("download/DPS_Login_Gateway", "DPS_Login_Gateway");
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/download/djson")
|
||||
public ResponseEntity<Resource> downloadFileDjson() {
|
||||
return getResourceResponseEntity("download/config.json", "config.json");
|
||||
}
|
||||
|
||||
@GetMapping("/download/dsh")
|
||||
public ResponseEntity<Resource> downloadFileDsh() {
|
||||
return getResourceResponseEntity("download/DpsLoginRestartSh", "DpsLoginRestartSh");
|
||||
}
|
||||
@GetMapping("/download/ddsh")
|
||||
public ResponseEntity<Resource> downloadFileDrsh() {
|
||||
return getResourceResponseEntity("download/DpsLoginDownloadSh", "DpsLoginDownloadSh");
|
||||
}
|
||||
|
||||
private ResponseEntity<Resource> getResourceResponseEntity(String x, String x1) {
|
||||
// 构建文件的完整路径
|
||||
File file = new File(fileManage.getFile() + x);
|
||||
if (!file.exists()) {
|
||||
// 如果文件不存在,返回 404 错误
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
// 创建文件资源对象
|
||||
Resource resource = new FileSystemResource(file);
|
||||
|
||||
// 设置响应头,告知浏览器这是一个附件,需要下载
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + x1);
|
||||
|
||||
// 返回响应实体,包含文件资源、响应头和状态码
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.contentLength(file.length())
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/download/jdk")
|
||||
public ResponseEntity<Resource> downloadFileJdk() {
|
||||
// 构建文件的完整路径
|
||||
return getResourceResponseEntity("jdk", "ndpsm_svr");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private RateLimiter globalRateLimiter;
|
||||
|
||||
@GetMapping("/download/jar")
|
||||
public ResponseEntity<Resource> downloadFilejar(HttpServletResponse response) {
|
||||
File file = new File(fileManage.getFile()+"download/RT.tar.gz");
|
||||
if (!file.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
try (InputStream inputStream = Files.newInputStream(file.toPath());
|
||||
BufferedInputStream bis = new BufferedInputStream(inputStream);
|
||||
OutputStream os = response.getOutputStream()) {
|
||||
|
||||
// 设置响应头
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=RT.tar.gz");
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
response.setContentLengthLong(file.length());
|
||||
|
||||
byte[] buffer = new byte[1024 * 8]; // 8KB 缓冲区
|
||||
int bytesRead;
|
||||
|
||||
// 动态限速:每次读取后根据数据量申请令牌
|
||||
while ((bytesRead = bis.read(buffer)) != -1) {
|
||||
// 申请令牌(阻塞直到获取足够令牌)
|
||||
globalRateLimiter.acquire(bytesRead);
|
||||
os.write(buffer, 0, bytesRead);
|
||||
os.flush();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
return ResponseEntity.status(500).build();
|
||||
}
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/download/all")
|
||||
public ResponseEntity<Resource> downloadFileall(@RequestBody Map<String,String> body,HttpServletResponse response) {
|
||||
String s = body.get("key");
|
||||
|
||||
FileReader fileReader = new FileReader(fileManage.getFilemap());
|
||||
String result = fileReader.readString();
|
||||
JSONObject jsonObject = JSONUtil.parseObj(result);
|
||||
String str = jsonObject.getStr(s);
|
||||
|
||||
File file = new File(str);
|
||||
StaticLog.info("请求下载文件"+file);
|
||||
|
||||
if (!file.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
try (InputStream inputStream = Files.newInputStream(file.toPath());
|
||||
BufferedInputStream bis = new BufferedInputStream(inputStream);
|
||||
OutputStream os = response.getOutputStream()) {
|
||||
|
||||
// 设置响应头
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=RT.tar.gz");
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
response.setContentLengthLong(file.length());
|
||||
|
||||
byte[] buffer = new byte[1024 * 8]; // 8KB 缓冲区
|
||||
int bytesRead;
|
||||
|
||||
// 动态限速:每次读取后根据数据量申请令牌
|
||||
while ((bytesRead = bis.read(buffer)) != -1) {
|
||||
// 申请令牌(阻塞直到获取足够令牌)
|
||||
globalRateLimiter.acquire(bytesRead);
|
||||
os.write(buffer, 0, bytesRead);
|
||||
os.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return ResponseEntity.status(500).build();
|
||||
}
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@RequestMapping("/download/gr")
|
||||
public ResponseEntity<Resource> downloadFilegr(String body,HttpServletResponse response) {
|
||||
|
||||
FileReader fileReader = new FileReader(fileManage.getFilemap());
|
||||
String result = fileReader.readString();
|
||||
JSONObject jsonObject = JSONUtil.parseObj(result);
|
||||
String str = jsonObject.getStr(body);
|
||||
|
||||
File file = new File(str);
|
||||
StaticLog.info("请求下载文件"+file);
|
||||
|
||||
if (!file.exists()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
try (InputStream inputStream = Files.newInputStream(file.toPath());
|
||||
BufferedInputStream bis = new BufferedInputStream(inputStream);
|
||||
OutputStream os = response.getOutputStream()) {
|
||||
|
||||
// 设置响应头
|
||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+file.getName());
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
response.setContentLengthLong(file.length());
|
||||
|
||||
byte[] buffer = new byte[1024 * 8]; // 8KB 缓冲区
|
||||
int bytesRead;
|
||||
|
||||
// 动态限速:每次读取后根据数据量申请令牌
|
||||
while ((bytesRead = bis.read(buffer)) != -1) {
|
||||
// 申请令牌(阻塞直到获取足够令牌)
|
||||
globalRateLimiter.acquire(bytesRead);
|
||||
os.write(buffer, 0, bytesRead);
|
||||
os.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return ResponseEntity.status(500).build();
|
||||
}
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/getversion")
|
||||
public String getversion() {
|
||||
|
||||
FileReader fileReader = new FileReader(fileManage.getFile()+"download/version");
|
||||
String result = fileReader.readString();
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping("/getmp4/{colonPath}/{img}")
|
||||
public ResponseEntity<Resource> streamVideo(
|
||||
@RequestHeader(value = "Range", required = false) String rangeHeader, @PathVariable String colonPath,@PathVariable String img) {
|
||||
|
||||
try {
|
||||
String decodedPath = URLDecoder.decode(colonPath, "UTF-8");
|
||||
img = URLDecoder.decode(img, "UTF-8");
|
||||
|
||||
Project byName = projectPerService.getByName(decodedPath);
|
||||
|
||||
if (byName==null)return null;
|
||||
String imgPath = byName.getImgPath();
|
||||
|
||||
Path videoPath = Paths.get("/root/rindro/Script/Project/"+imgPath+"/vid/"+img+".mp4");
|
||||
|
||||
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if (os.contains("win")) {
|
||||
videoPath = Paths.get("C:\\Users\\12134\\Desktop\\工作目录\\rindro\\Script\\Project\\"+imgPath+"\\vid\\"+img+".mp4");
|
||||
}
|
||||
|
||||
Resource videoResource = new UrlResource(videoPath.toUri());
|
||||
|
||||
if (!videoResource.exists() || !videoResource.isReadable()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
long contentLength = videoResource.contentLength();
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("video/mp4"));
|
||||
headers.set("Accept-Ranges", "bytes");
|
||||
|
||||
if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
|
||||
String[] ranges = rangeHeader.substring(6).split("-");
|
||||
long start = Long.parseLong(ranges[0]);
|
||||
long end = (ranges.length > 1 && !ranges[1].isEmpty())
|
||||
? Long.parseLong(ranges[1])
|
||||
: contentLength - 1;
|
||||
long rangeLength = end - start + 1;
|
||||
|
||||
if (start >= contentLength || end >= contentLength) {
|
||||
return ResponseEntity.status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE)
|
||||
.header("Content-Range", "bytes */" + contentLength)
|
||||
.build();
|
||||
}
|
||||
|
||||
// 获取输入流并跳过起始字节
|
||||
InputStream inputStream = videoResource.getInputStream();
|
||||
long skippedBytes = inputStream.skip(start);
|
||||
if (skippedBytes != start) {
|
||||
throw new IOException("无法跳过指定字节数");
|
||||
}
|
||||
|
||||
headers.set("Content-Range", "bytes " + start + "-" + end + "/" + contentLength);
|
||||
headers.setContentLength(rangeLength);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
|
||||
.headers(headers)
|
||||
.body(new InputStreamResource(inputStream));
|
||||
} else {
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.body(videoResource);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
}
|
||||
|
||||
//根据ip获取插件列表
|
||||
@PostMapping("/getServerProList")
|
||||
public ResponseEntity<CommonResult<List<UserServerProject>>> getServerList(@RequestBody Map<String,String> body, @CurrentUserId String userName){
|
||||
if (userAndServerService.selectCount(body.get("ip"),userName)==0){
|
||||
return ResponseEntity.ok(CommonResult.success(null));
|
||||
}
|
||||
List<UserServerProject> ip = userServerProjectService.getpro(body.get("ip"));
|
||||
return ResponseEntity.ok(CommonResult.success(ip));
|
||||
}
|
||||
|
||||
//设置用户单机用的key值
|
||||
@PostMapping("/setKey")
|
||||
public ResponseEntity<CommonResult<String>> setKey(@RequestBody Map<String,String> body, @CurrentUserId String userName){
|
||||
|
||||
String s = userService.setKey(userName, body.get("clientkey"), body.get("serverkey"));
|
||||
|
||||
return ResponseEntity.ok(CommonResult.success(s));
|
||||
}
|
||||
|
||||
@PostMapping("/setproopen")
|
||||
public ResponseEntity<CommonResult<String>> setproOpen(@RequestBody Map<String,String> body, @CurrentUserId String userName){
|
||||
String s = userServerProjectService.setproOpen(body.get("ip"), body.get("projectName"), body.get("open"),userName);
|
||||
return ResponseEntity.ok(CommonResult.success(s));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.example.sjkbf.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-19
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/user-server-project")
|
||||
public class UserServerProjectController {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
package com.example.sjkbf.controller;
|
||||
|
||||
import com.example.sjkbf.entity.projectconfig.Project;
|
||||
import com.example.sjkbf.service.ProjectPerService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.*;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.io.*;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.file.*;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class VideoController {
|
||||
|
||||
private static final String VIDEO_ROOT = "/root/rindro/Script/Project";
|
||||
private static final String TRANSCODE_ROOT = "/tmp/video-transcoded";
|
||||
|
||||
private final ExecutorService transcodeExecutor = Executors.newFixedThreadPool(4);
|
||||
|
||||
@Autowired
|
||||
private ProjectPerService projectPerService;
|
||||
private final DecimalFormat durationFormat = new DecimalFormat("0.00");
|
||||
|
||||
@GetMapping("/videos/{project}/{videoName}")
|
||||
public ResponseEntity<Resource> streamVideo(
|
||||
@PathVariable String project,
|
||||
@PathVariable String videoName,
|
||||
@RequestHeader(value = "User-Agent", required = false) String userAgent,
|
||||
@RequestHeader(value = "Range", required = false) String rangeHeader) throws Exception {
|
||||
|
||||
System.out.println("原始参数 - project: " + project + ", videoName: " + videoName);
|
||||
|
||||
// project ="project";
|
||||
// videoName = "0";
|
||||
// 直接使用 Spring 已经解码的参数
|
||||
project = projectPerService.getByName(project).getImgPath();
|
||||
|
||||
// project = projectPerService.getByName(decodedPath).getImgPath();
|
||||
|
||||
Path sourcePath = Paths.get(VIDEO_ROOT, project, "vid", videoName + ".mp4");
|
||||
|
||||
// 检查源文件是否存在
|
||||
if (!Files.exists(sourcePath)) {
|
||||
System.out.println("源文件不存在: " + sourcePath);
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
boolean needsTranscode = needsTranscode(sourcePath, userAgent);
|
||||
|
||||
if (needsTranscode) {
|
||||
Path transcodedPath = getTranscodedPath(project, videoName);
|
||||
|
||||
// 如果转码文件不存在或正在转码,先返回原始文件
|
||||
if (!Files.exists(transcodedPath) || isTranscodingInProgress(transcodedPath)) {
|
||||
// 异步触发转码(如果还没开始的话)
|
||||
if (!Files.exists(transcodedPath)) {
|
||||
startTranscode(project, videoName);
|
||||
}
|
||||
// 返回原始文件作为降级方案
|
||||
return buildVideoResponse(sourcePath, rangeHeader, false);
|
||||
}
|
||||
|
||||
return buildVideoResponse(transcodedPath, rangeHeader, true);
|
||||
} else {
|
||||
return buildVideoResponse(sourcePath, rangeHeader, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 改进的转码检测逻辑
|
||||
*/
|
||||
private boolean needsTranscode(Path videoPath, String userAgent) throws IOException {
|
||||
if (!Files.exists(videoPath)) {
|
||||
throw new FileNotFoundException("视频文件不存在: " + videoPath);
|
||||
}
|
||||
|
||||
// 不再强制为移动设备转码,而是基于实际编码格式判断
|
||||
try {
|
||||
// 检测视频编码
|
||||
String videoCodec = getStreamCodec(videoPath, "v");
|
||||
String audioCodec = getStreamCodec(videoPath, "a");
|
||||
|
||||
// 需要转码的情况:
|
||||
// 1. 视频不是H.264
|
||||
// 2. 音频不是AAC或MP3
|
||||
boolean needTranscode = !"h264".equalsIgnoreCase(videoCodec) ||
|
||||
(!"aac".equalsIgnoreCase(audioCodec) && !"mp3".equalsIgnoreCase(audioCodec));
|
||||
|
||||
System.out.println("视频编码: " + videoCodec + ", 音频编码: " + audioCodec + ", 需要转码: " + needTranscode);
|
||||
return needTranscode;
|
||||
|
||||
} catch (Exception e) {
|
||||
// 如果检测失败,默认需要转码
|
||||
System.err.println("编码检测失败,默认需要转码: " + e.getMessage());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取音视频流编码
|
||||
*/
|
||||
private String getStreamCodec(Path videoPath, String streamType) throws IOException {
|
||||
Process proc = new ProcessBuilder(
|
||||
"ffprobe",
|
||||
"-v", "error",
|
||||
"-select_streams", streamType + ":0",
|
||||
"-show_entries", "stream=codec_name",
|
||||
"-of", "default=noprint_wrappers=1:nokey=1",
|
||||
videoPath.toString()
|
||||
).start();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
|
||||
String codec = br.readLine();
|
||||
return codec != null ? codec.trim() : "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取转码路径并触发转码
|
||||
*/
|
||||
private Path getTranscodedPath(String project, String videoName) {
|
||||
return Paths.get(TRANSCODE_ROOT, project, videoName + "_h264.mp4");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动转码任务
|
||||
*/
|
||||
private void startTranscode(String project, String videoName) {
|
||||
transcodeExecutor.submit(() -> transcodeVideo(project, videoName));
|
||||
}
|
||||
|
||||
/**
|
||||
* 改进的转码方法 - 使用更兼容的参数
|
||||
*/
|
||||
private void transcodeVideo(String project, String videoName) {
|
||||
Path transcodedPath = getTranscodedPath(project, videoName);
|
||||
Path tempPath = Paths.get(transcodedPath.toString() + ".tmp");
|
||||
|
||||
try {
|
||||
// 确保目录存在
|
||||
Files.createDirectories(transcodedPath.getParent());
|
||||
|
||||
String source = Paths.get(VIDEO_ROOT, project, "vid", videoName + ".mp4").toString();
|
||||
|
||||
// 简化转码命令 - 提高兼容性
|
||||
String[] cmd = {
|
||||
"ffmpeg", "-i", source,
|
||||
"-c:v", "libx264",
|
||||
"-preset", "medium",
|
||||
"-crf", "23",
|
||||
"-profile:v", "high", // 改为high提高质量
|
||||
"-level", "4.0",
|
||||
"-c:a", "aac",
|
||||
"-b:a", "128k",
|
||||
"-movflags", "+faststart", // 只保留faststart
|
||||
"-y", tempPath.toString() // 先输出到临时文件
|
||||
};
|
||||
|
||||
System.out.println("执行转码命令: " + String.join(" ", cmd));
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmd);
|
||||
pb.redirectErrorStream(true);
|
||||
Process p = pb.start();
|
||||
|
||||
// 读取输出用于调试
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println("FFmpeg: " + line);
|
||||
}
|
||||
}
|
||||
|
||||
int exitCode = p.waitFor();
|
||||
|
||||
if (exitCode == 0) {
|
||||
// 转码成功,重命名临时文件
|
||||
Files.move(tempPath, transcodedPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
System.out.println("转码完成: " + transcodedPath);
|
||||
} else {
|
||||
System.err.println("转码失败,退出码: " + exitCode);
|
||||
Files.deleteIfExists(tempPath);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("转码过程出错: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
try {
|
||||
Files.deleteIfExists(tempPath);
|
||||
} catch (IOException ioException) {
|
||||
ioException.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否正在转码
|
||||
*/
|
||||
private boolean isTranscodingInProgress(Path transcodedPath) {
|
||||
Path tempPath = Paths.get(transcodedPath.toString() + ".tmp");
|
||||
return Files.exists(tempPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查原始文件是否比转码文件新
|
||||
*/
|
||||
private boolean isSourceNewer(String project, String videoName, Path transcodedPath) throws IOException {
|
||||
Path sourcePath = Paths.get(VIDEO_ROOT, project, "vid", videoName + ".mp4");
|
||||
return Files.getLastModifiedTime(sourcePath).toInstant()
|
||||
.isAfter(Files.getLastModifiedTime(transcodedPath).toInstant());
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建视频响应
|
||||
*/
|
||||
private ResponseEntity<Resource> buildVideoResponse(Path videoPath, String rangeHeader, boolean isTranscoded)
|
||||
throws IOException {
|
||||
|
||||
if (!Files.exists(videoPath)) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
Resource resource = new FileSystemResource(videoPath);
|
||||
long fileLength = resource.contentLength();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Accept-Ranges", "bytes");
|
||||
headers.set("Content-Disposition", "inline");
|
||||
|
||||
// 处理范围请求
|
||||
if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
|
||||
String range = rangeHeader.substring(6);
|
||||
String[] ranges = range.split("-");
|
||||
|
||||
long start = Long.parseLong(ranges[0]);
|
||||
long end = ranges.length > 1 ? Long.parseLong(ranges[1]) : fileLength - 1;
|
||||
long rangeLength = end - start + 1;
|
||||
|
||||
if (rangeLength < 0 || start < 0 || end >= fileLength) {
|
||||
return ResponseEntity.status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE)
|
||||
.header("Content-Range", "bytes */" + fileLength)
|
||||
.build();
|
||||
}
|
||||
|
||||
headers.set("Content-Range", "bytes " + start + "-" + end + "/" + fileLength);
|
||||
headers.setContentLength(rangeLength);
|
||||
|
||||
// 读取部分内容
|
||||
InputStreamResource inputStreamResource = createPartialContent(resource, start, rangeLength);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
|
||||
.headers(headers)
|
||||
.contentType(MediaType.parseMediaType("video/mp4"))
|
||||
.body(inputStreamResource);
|
||||
}
|
||||
|
||||
// 完整文件响应
|
||||
headers.setContentLength(fileLength);
|
||||
headers.set("Content-Type", "video/mp4");
|
||||
headers.set("X-Content-Duration", getVideoDuration(videoPath));
|
||||
headers.set("Cache-Control", isTranscoded ? "public, max-age=2592000" : "no-cache");
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建部分内容资源
|
||||
*/
|
||||
private InputStreamResource createPartialContent(Resource resource, long start, long length) throws IOException {
|
||||
InputStream inputStream = resource.getInputStream();
|
||||
inputStream.skip(start);
|
||||
|
||||
return new InputStreamResource(inputStream) {
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new LimitedInputStream(inputStream, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() throws IOException {
|
||||
return length;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 限制输入流
|
||||
*/
|
||||
private static class LimitedInputStream extends InputStream {
|
||||
private final InputStream wrapped;
|
||||
private long remaining;
|
||||
|
||||
public LimitedInputStream(InputStream wrapped, long limit) {
|
||||
this.wrapped = wrapped;
|
||||
this.remaining = limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (remaining <= 0) return -1;
|
||||
int result = wrapped.read();
|
||||
if (result != -1) remaining--;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (remaining <= 0) return -1;
|
||||
int toRead = (int) Math.min(len, remaining);
|
||||
int result = wrapped.read(b, off, toRead);
|
||||
if (result != -1) remaining -= result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取视频时长
|
||||
*/
|
||||
private String getVideoDuration(Path videoPath) throws IOException {
|
||||
try {
|
||||
Process proc = new ProcessBuilder(
|
||||
"ffprobe", "-v", "error",
|
||||
"-show_entries", "format=duration",
|
||||
"-of", "default=noprint_wrappers=1:nokey=1",
|
||||
videoPath.toString()
|
||||
).start();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
|
||||
String duration = br.readLine();
|
||||
if (duration != null && !duration.trim().isEmpty()) {
|
||||
return durationFormat.format(Double.parseDouble(duration.trim()));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("获取视频时长失败: " + e.getMessage());
|
||||
}
|
||||
return "0.00";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.example.sjkbf.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.example.sjkbf.config.Configuration.CurrentUserId;
|
||||
import com.example.sjkbf.entity.CommonResult;
|
||||
import com.example.sjkbf.service.UserOrderService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
@RestController()
|
||||
@RequestMapping("/zf")
|
||||
|
||||
public class ZfController {
|
||||
|
||||
String payKey = "8658ea66fbbe4a1aad4691ddecefe5fa";
|
||||
|
||||
String payUrl = "https://2277883.pay.lanjingzf.com/createOrder?";
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserOrderService service;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param payId 商户订单号
|
||||
* @param param 创建订单的时候传入的参数
|
||||
* @param type 支付方式 :微信支付为1 支付宝支付为2
|
||||
* @param price 订单金额
|
||||
* @param reallyPrice 实际支付金额
|
||||
* @param sign 校验签名,计算方式 = md5(payId + param + type + price + reallyPrice + 通讯密钥)
|
||||
*/
|
||||
@RequestMapping("callback")
|
||||
public String callback(@RequestParam String payId,@RequestParam String param,@RequestParam Integer type, @RequestParam Float price,@RequestParam Float reallyPrice,@RequestParam String sign){
|
||||
|
||||
System.out.println(payId);
|
||||
System.out.println(param);
|
||||
System.out.println(type);
|
||||
System.out.println(price);
|
||||
System.out.println(reallyPrice);
|
||||
System.out.println(sign);
|
||||
|
||||
|
||||
|
||||
return service.callback(payId, param, type, price, reallyPrice, sign);
|
||||
}
|
||||
|
||||
@RequestMapping("create")
|
||||
public ResponseEntity<CommonResult<String>> create(@RequestBody Map<String,Integer> body, @CurrentUserId String userName) throws IOException {
|
||||
|
||||
String s = service.create(body.get("type"), body.get("price"), userName);
|
||||
|
||||
return ResponseEntity.ok( CommonResult.success(s));
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException, IOException {
|
||||
UserOrderService service = new UserOrderService();
|
||||
String s = service.create(1, 1, "123");
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,729 @@
|
||||
package com.example.sjkbf.controller;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.asymmetric.RSA;
|
||||
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.sjkbf.common.FileManage;
|
||||
import com.example.sjkbf.entity.CommonResult;
|
||||
import com.example.sjkbf.entity.DPSScriptJson;
|
||||
import com.example.sjkbf.entity.User;
|
||||
import com.example.sjkbf.entity.UserServerProject;
|
||||
import com.example.sjkbf.entity.projectconfig.ProjectConfig;
|
||||
import com.example.sjkbf.service.ProjectPerService;
|
||||
import com.example.sjkbf.service.UserServerProjectService;
|
||||
import com.example.sjkbf.service.UserService;
|
||||
import com.example.sjkbf.service.impl.ProjectPerServiceImpl;
|
||||
import com.example.sjkbf.util.RSATooL;
|
||||
import com.example.sjkbf.util.SimpleNutZipCompatible;
|
||||
import com.example.sjkbf.util.tool;
|
||||
import org.checkerframework.checker.units.qual.A;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/script")
|
||||
public class verifyController {
|
||||
|
||||
@Autowired
|
||||
private UserServerProjectService userServerProjectService;
|
||||
|
||||
@Autowired
|
||||
private ProjectPerService projectPerService;
|
||||
|
||||
@Autowired
|
||||
private FileManage fileManage;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
|
||||
public static Map<String,String> ipAndMac=new HashMap<>();
|
||||
|
||||
|
||||
|
||||
@RequestMapping("client")
|
||||
public ResponseEntity<String> client(String ip,String clientKey,String ve) {
|
||||
|
||||
if (ve == null )ve = "1.0";
|
||||
System.out.println( ve);
|
||||
StaticLog.info(ip+" client 客户端 请求验证");
|
||||
|
||||
List<UserServerProject> getpro=new ArrayList<>();
|
||||
// if (ip.equals("192.168.200.131")){
|
||||
// User clientKey1 = userService.getOne(new QueryWrapper<User>().eq("client_key", clientKey));
|
||||
//
|
||||
// getpro = userServerProjectService.getByUserName(clientKey1.getName());
|
||||
//
|
||||
// }else {
|
||||
|
||||
getpro = userServerProjectService.getproAndOpen(ip);
|
||||
// }
|
||||
|
||||
int[] key = new int[20];
|
||||
StringBuilder keys= new StringBuilder();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
key[i]=(RandomUtil.randomInt(1, 9));
|
||||
keys.append(key[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
List<String> BaseScriptStr = projectPerService.getBaseScriptStrEncrypt(key,ve);
|
||||
|
||||
|
||||
//如果项目里有cs 就发测试base
|
||||
for (UserServerProject userServerProject : getpro) {
|
||||
if (userServerProject.getProjectName().equals("cs")){
|
||||
BaseScriptStr = projectPerService.getCSBaseScriptStrEncrypt(key,ve);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!getpro.isEmpty()) {
|
||||
for (UserServerProject userServerProject : getpro) {
|
||||
String projectName = userServerProject.getProjectName();
|
||||
if (projectName.equals("cs"))continue;
|
||||
|
||||
List<String> projectScriptStrEncrypt = projectPerService.getProjectScriptStrEncrypt(projectName, key,ve);
|
||||
BaseScriptStr.addAll(projectScriptStrEncrypt);
|
||||
System.out.println(projectName + " 加载" + projectScriptStrEncrypt.size() + "个文件");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(BaseScriptStr.size());
|
||||
List<String> projectScriptStrEncrypt = projectPerService.getzdy(ip, key,ve);
|
||||
if (!projectScriptStrEncrypt.isEmpty()) {
|
||||
BaseScriptStr.addAll(projectScriptStrEncrypt);
|
||||
System.out.println("加载自定义脚本" + projectScriptStrEncrypt.size() + "个文件");
|
||||
}
|
||||
|
||||
|
||||
System.out.println(BaseScriptStr.size());
|
||||
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (String s : BaseScriptStr) {
|
||||
|
||||
|
||||
stringBuilder.append(s);
|
||||
stringBuilder.append("$$$$$");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("getBaseScriptStr",stringBuilder.toString());
|
||||
json.set("key", RSATooL.encryption(keys.toString()));
|
||||
String string = json.toString();
|
||||
String compress = RSATooL.compress(string);
|
||||
|
||||
|
||||
return ResponseEntity.ok(compress);
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("getzdy")
|
||||
public String getzdy( HttpServletRequest request,String ve) {
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
// 如果应用部署在反向代理或负载均衡器后面,可以通过X-Forwarded-For头部获取真实IP地址
|
||||
String forwardedFor = request.getHeader("X-Forwarded-For");
|
||||
if (forwardedFor != null && !forwardedFor.isEmpty()) {
|
||||
ipAddress = forwardedFor.split(",")[0];
|
||||
}
|
||||
|
||||
|
||||
System.out.println(ipAddress + "请求自定义脚本");
|
||||
|
||||
List<String> projectScriptStrEncrypt = projectPerService.getzdy2(ipAddress,ve);
|
||||
if (!projectScriptStrEncrypt.isEmpty()) {
|
||||
System.out.println("加载自定义脚本" + projectScriptStrEncrypt.size() + "个文件");
|
||||
}else {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
// StringBuilder stringBuilder = new StringBuilder();
|
||||
// for (String s : projectScriptStrEncrypt) {
|
||||
//
|
||||
//
|
||||
// stringBuilder.append(s);
|
||||
// stringBuilder.append("$$$$$");
|
||||
// }
|
||||
|
||||
JSONObject json = new JSONObject();
|
||||
json.set("getBaseScriptStr",projectScriptStrEncrypt);
|
||||
String string = json.toString();
|
||||
|
||||
// String compress = RSATooL.compress(string);//压缩
|
||||
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("client2")
|
||||
public ResponseEntity<Map<String, Object>> client2(String ip,String clientKey,String ve) {
|
||||
System.out.println( ve);
|
||||
StaticLog.info(ip+"client2 客户端 请求验证");
|
||||
|
||||
List<UserServerProject> getpro=new ArrayList<>();
|
||||
// if (ip.equals("192.168.200.131")){
|
||||
// User clientKey1 = userService.getOne(new QueryWrapper<User>().eq("client_key", clientKey));
|
||||
//
|
||||
// getpro = userServerProjectService.getByUserName(clientKey1.getName());
|
||||
//
|
||||
// }else {
|
||||
|
||||
getpro = userServerProjectService.getproAndOpen(ip);
|
||||
// }
|
||||
|
||||
int[] key = new int[20];
|
||||
StringBuilder keys= new StringBuilder();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
key[i]=(RandomUtil.randomInt(1, 9));
|
||||
keys.append(key[i]);
|
||||
}
|
||||
|
||||
List<byte[]> BaseScriptStr = projectPerService.getBaseScriptStrEncrypt2(key,ve);
|
||||
|
||||
if (!getpro.isEmpty()) {
|
||||
for (UserServerProject userServerProject : getpro) {
|
||||
String projectName = userServerProject.getProjectName();
|
||||
List<byte[]> projectScriptStrEncrypt = projectPerService.getProjectScriptStrEncrypt2(projectName, key,ve);
|
||||
BaseScriptStr.addAll(projectScriptStrEncrypt);
|
||||
System.out.println(projectName + " 加载" + projectScriptStrEncrypt.size() + "个文件");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
map.put("getBaseScriptStr",BaseScriptStr);
|
||||
map.put("key",RSATooL.encryption(keys.toString()));
|
||||
|
||||
return ResponseEntity.ok(map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 服务端验证
|
||||
*/
|
||||
@PostMapping("getpro")
|
||||
public String getpro(HttpServletRequest request, String prot, Long l, String mac, String s){
|
||||
|
||||
String ipAddress = tool.getIpAddress(request);
|
||||
|
||||
long time = DateUtil.date().getTime();
|
||||
|
||||
StaticLog.info(ipAddress+"服务端 请求验证");
|
||||
|
||||
if (Math.abs(time - l)>1000*60*5||mac==null||mac.isEmpty()||prot==null||prot.isEmpty()){
|
||||
|
||||
StaticLog.info(ipAddress+"服务端 请求验证失败");
|
||||
StaticLog.info(String.valueOf(Math.abs(time - l)>1000*60*5));
|
||||
StaticLog.info(String.valueOf(mac==null||mac.isEmpty()));
|
||||
StaticLog.info(String.valueOf(prot==null||prot.isEmpty()));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
String s1 = ipAndMac.get(ipAddress);
|
||||
|
||||
if (s1==null||s1.isEmpty()){
|
||||
ipAndMac.put(ipAddress,mac);
|
||||
s1 = mac;
|
||||
}
|
||||
if (!s1.equals(mac)){
|
||||
//不同的md5值 记录日志
|
||||
StaticLog.error("md5值和之前不相同 :" + ipAddress);
|
||||
}
|
||||
|
||||
List<UserServerProject> getpro = userServerProjectService.getproAndOpen(ipAddress);
|
||||
if (getpro.isEmpty()) {
|
||||
StaticLog.error("验证错误" + ipAddress);
|
||||
return null;
|
||||
}
|
||||
StringBuilder pro = new StringBuilder();
|
||||
for (UserServerProject userServerProject : getpro) {
|
||||
pro.append(userServerProject.getProjectName()).append(",");
|
||||
}
|
||||
Map<String,Object> body=new HashMap<>();
|
||||
body.put("pro", pro.toString());
|
||||
body.put("validate",time);
|
||||
body.put("ce",s);
|
||||
//生成一个唯一的id 作为穿给中间件的验证值 存到redis 中
|
||||
String key = IdUtil.simpleUUID();
|
||||
body.put("key",key);
|
||||
body.put("ip",ipAddress);
|
||||
|
||||
|
||||
StaticLog.info(ipAddress+"服务端 通过验证");
|
||||
String jsonStr = JSONUtil.toJsonStr(body);
|
||||
return tool.encryption(jsonStr);
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("getservice")
|
||||
public ResponseEntity<String> getservice( HttpServletRequest request,String ser) throws IOException {
|
||||
StaticLog.info("收到服务器的getservice2请求脚本");
|
||||
|
||||
// 获取客户端IP地址
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
|
||||
// 如果应用部署在反向代理或负载均衡器后面,可以通过X-Forwarded-For头部获取真实IP地址
|
||||
String forwardedFor = request.getHeader("X-Forwarded-For");
|
||||
if (forwardedFor != null && !forwardedFor.isEmpty()) {
|
||||
ipAddress = forwardedFor.split(",")[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int[] intArray1 = new int[20];
|
||||
StringBuilder keys= new StringBuilder();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
intArray1[i]=(RandomUtil.randomInt(1, 9));
|
||||
keys.append(intArray1[i]);
|
||||
}
|
||||
|
||||
|
||||
//项目map
|
||||
Map<String, byte[]> stringStringMap=new HashMap<>();
|
||||
List<String> stringStringMapSX=new ArrayList<>();
|
||||
|
||||
|
||||
List<UserServerProject> getpro = userServerProjectService.getproAndOpen(ipAddress);
|
||||
|
||||
|
||||
if (getpro.isEmpty()) {
|
||||
//把通用的数据线丢到map中
|
||||
List<String> strings333 = FileUtil.readUtf8Lines(fileManage.getDpsScriptfile()+"base2/config");
|
||||
for (String s : strings333) {
|
||||
File file2 = FileUtil.file(fileManage.getDpsScriptfile()+"base2/" + s);
|
||||
FileReader fileReader1 = new FileReader(fileManage.getDpsScriptfile()+"base2/" + s);
|
||||
|
||||
stringStringMap.put(fileManage.getDpsScriptfile()+"base2/" + s, fileReader1.readString().getBytes());
|
||||
stringStringMapSX.add(fileManage.getDpsScriptfile()+"base2/" + s);
|
||||
}
|
||||
|
||||
System.out.println("通过了 没买插件的验证");
|
||||
|
||||
}else {
|
||||
|
||||
if (ipAddress .equals("112.12.194.152") || ipAddress .equals("202.189.14.166") || ipAddress .equals("45.125.44.2") || ipAddress .equals("110.42.110.159")|| ipAddress .equals("202.189.14.111")){
|
||||
//把通用的数据线丢到map中
|
||||
List<String> strings333 = FileUtil.readUtf8Lines(fileManage.getDpsScriptfile()+"" +
|
||||
"" +
|
||||
"base3/config");
|
||||
for (String s : strings333) {
|
||||
File file2 = FileUtil.file(fileManage.getDpsScriptfile()+"base3/" + s);
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
|
||||
stringStringMap.put(fileManage.getDpsScriptfile()+"base3/" + s, fileReader1 .readString().getBytes());
|
||||
stringStringMapSX.add(fileManage.getDpsScriptfile()+"base3/" + s);
|
||||
}
|
||||
}else {
|
||||
//把通用的数据线丢到map中
|
||||
List<String> strings333 = FileUtil.readUtf8Lines(fileManage.getDpsScriptfile()+"base/config");
|
||||
for (String s : strings333) {
|
||||
File file2 = FileUtil.file(fileManage.getDpsScriptfile()+"base/" + s);
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
|
||||
stringStringMap.put(fileManage.getDpsScriptfile()+"base/" + s, fileReader1 .readString().getBytes());
|
||||
stringStringMapSX.add(fileManage.getDpsScriptfile()+"base/" + s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//从数据库找到所有的插件
|
||||
for (UserServerProject user2 : getpro) {
|
||||
String chajian = user2.getProjectName();
|
||||
|
||||
String s1 = fileManage.getDpsScriptfile() + "project/" + chajian;
|
||||
Path path = Paths.get(s1);
|
||||
//根据插件获得服务器的插件路径 然后以路径为key 里面的值为v 存入到map中 之后加密返回
|
||||
if (Files.exists(path)) {
|
||||
List<String> strings444 = FileUtil.readUtf8Lines(s1 + "/config");
|
||||
for (String s : strings444) {
|
||||
File file2 = FileUtil.file(s1 + "/" + s);
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
stringStringMap.put(s1 + "/" + s, fileReader1.readString().getBytes());
|
||||
stringStringMapSX.add(s1 + "/" + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File file2 = FileUtil.file(fileManage.getDpsScriptfile() + "user/通用/main.nut");
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
stringStringMap.put(fileManage.getDpsScriptfile() + "user/通用/main.nut", fileReader1.readString().getBytes());
|
||||
stringStringMapSX.add(fileManage.getDpsScriptfile() + "user/通用/main.nut");
|
||||
}
|
||||
|
||||
if (ipAddress .equals("112.12.194.152") || ipAddress .equals("202.189.14.166") || ipAddress .equals("45.125.44.2") || ipAddress .equals("110.42.110.159")|| ipAddress .equals("202.189.14.111")){
|
||||
for (String stringMapSX : stringStringMapSX) {
|
||||
System.out.println(stringMapSX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//以下代码为从/root/rindro/dpsScript/user/ 目录中加载自定义的服务端脚本
|
||||
String s1 = fileManage.getDpsScriptfile() + "user/" + ipAddress;
|
||||
Path path = Paths.get(s1);
|
||||
if (Files.exists(path)) {
|
||||
List<String> strings444 = FileUtil.readUtf8Lines(s1 + "/config");
|
||||
for (String s : strings444) {
|
||||
File file2 = FileUtil.file(s1 + "/" + s);
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
stringStringMap.put(s1 + "/" + s, fileReader1.readString().getBytes());
|
||||
stringStringMapSX.add(s1 + "/" + s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Map<String, byte[]> stringStringMapUser=new HashMap<>();
|
||||
// List<String> stringStringMapUserSX=new ArrayList<>();
|
||||
|
||||
// try {
|
||||
// List<String> strings2222 = FileUtil.readUtf8Lines("/root/rindro/user/"+ipAddress + "/serConfig");
|
||||
//
|
||||
// for (String s : strings2222) {
|
||||
// File file2 = FileUtil.file("/root/rindro/user/"+ipAddress + "/"+s);
|
||||
// FileReader fileReader = new FileReader(file2);
|
||||
// byte[] bytes = fileReader.readBytes();
|
||||
// stringStringMapUser.put("/root/rindro/user/"+ipAddress + "/"+s,bytes);
|
||||
// stringStringMapUserSX.add("/root/rindro/user/"+ipAddress + "/"+s);
|
||||
// }
|
||||
// }catch (Exception e){
|
||||
// System.out.println("未找到userip文件,外部用户请求");
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// 对通用文件进行加密处理
|
||||
for (Map.Entry<String, byte[]> entry : stringStringMap.entrySet()) {
|
||||
byte[] encryptedValue = RSATooL.Makecode(entry.getValue(), intArray1);
|
||||
entry.setValue(encryptedValue); // 直接在Map中更新值
|
||||
}
|
||||
|
||||
|
||||
// //对用户文件进行加密处理
|
||||
// for (Map.Entry<String, byte[]> entry : stringStringMapUser.entrySet()) {
|
||||
// byte[] encryptedValue = Main.Makecode(entry.getValue(), intArray1);
|
||||
// entry.setValue(encryptedValue); // 直接在Map中更新值
|
||||
// }
|
||||
|
||||
|
||||
StringBuilder sb=new StringBuilder();
|
||||
for (String string : stringStringMapSX) {
|
||||
sb.append(string);
|
||||
sb.append("$$$$$");
|
||||
String string1 = Arrays.toString(stringStringMap.get(string));
|
||||
|
||||
sb.append(string1, 1, string1.length()-1);
|
||||
|
||||
sb.append("$$$$$");
|
||||
}
|
||||
|
||||
// for (String string : stringStringMapUserSX) {
|
||||
// sb.append(string);
|
||||
// sb.append("$$$$");
|
||||
// sb.append(Arrays.toString(stringStringMapUser.get(string)));
|
||||
// sb.append("$$$$");
|
||||
// }
|
||||
String substring = sb.toString();
|
||||
StaticLog.info(ipAddress+"通过验证 返回dps nut脚本");
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.set("getBaseScriptStr",substring);
|
||||
json.set("key",RSATooL.encryption(keys.toString()));
|
||||
String string = json.toString();
|
||||
String compress = RSATooL.compress(string);
|
||||
|
||||
return ResponseEntity.ok(compress);
|
||||
}
|
||||
|
||||
Map<String,JSONObject> jsonObject=new HashMap<>();
|
||||
@RequestMapping ("getBaseUpdateTime")
|
||||
public ResponseEntity<String> getBaseUpdateTime(String ve) {
|
||||
|
||||
|
||||
if (ve == null) ve = "1.0";
|
||||
|
||||
// 1. 构建 base 目录路径(避免硬编码拼接,用 File 构造方法更安全)
|
||||
String baseDirPath = fileManage.getFile() + "/DP-S_Script/Script"+ve+"/_DPS_";
|
||||
File baseDir = new File(baseDirPath);
|
||||
|
||||
// 2. 校验目录合法性(不存在/不是目录直接返回 0)
|
||||
if (!baseDir.exists() || !baseDir.isDirectory()) {
|
||||
return ResponseEntity.ok("0");
|
||||
}
|
||||
|
||||
// 3. 递归遍历所有文件,获取最新修改时间
|
||||
long latestModifyTime = traverseAllFiles(baseDir);
|
||||
|
||||
// 4. 返回结果(时间戳转字符串)
|
||||
return ResponseEntity.ok(String.valueOf(latestModifyTime));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("getBaseSutZip")
|
||||
public ResponseEntity<Object> getBaseSut(HttpServletRequest request,@RequestParam(value = "ve", required = false) String ve) {
|
||||
nut_sut(ve);
|
||||
|
||||
|
||||
String file = fileManage.getFile() +"sut.tar.gz";
|
||||
|
||||
Path baseDir = Paths.get(file).toAbsolutePath().normalize();
|
||||
Resource resource = new FileSystemResource(baseDir);
|
||||
|
||||
// 设置响应头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"");
|
||||
|
||||
// 返回包含文件资源的通用结果
|
||||
return ResponseEntity.ok()
|
||||
.header("Content-Disposition",
|
||||
"attachment; filename=\"" + resource.getFilename() + "\"")
|
||||
.body(resource);
|
||||
}
|
||||
|
||||
Map<String,Long> updateTime=new HashMap<>();
|
||||
|
||||
|
||||
public void nut_sut(String bb) {
|
||||
if (bb ==null) bb = "1.0";
|
||||
String baseDirPath = fileManage.getFile() + "/DP-S_Script/Script"+bb+"/_DPS_";
|
||||
File baseDir = new File(baseDirPath);
|
||||
long latestModifyTime = traverseAllFiles(baseDir);
|
||||
|
||||
System.out.println("最新修改时间:" + latestModifyTime);
|
||||
System.out.println("updateTime:" + updateTime.get(bb));
|
||||
if ( updateTime.get(bb) == null || latestModifyTime > updateTime.get(bb)){
|
||||
//重新加密压缩
|
||||
|
||||
String targetPath = fileManage.getFile()+"sut.tar.gz";
|
||||
String key = "Rindro-Aurora";
|
||||
SimpleNutZipCompatible.encryptAndZip(baseDirPath, targetPath, key);
|
||||
|
||||
|
||||
updateTime.put(bb,traverseAllFiles(baseDir));
|
||||
|
||||
|
||||
FileReader fileReader = new FileReader(fileManage.getFile() + "/DP-S_Script/Script"+bb+"/_DPS_" + "/FileConfig.json");
|
||||
String result5 = fileReader.readString();
|
||||
//转json
|
||||
JSONObject jsonObject1 = new JSONObject(result5);
|
||||
jsonObject.put(bb,jsonObject1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@RequestMapping("getservicenew")
|
||||
public ResponseEntity<String> getservicenew( HttpServletRequest request,String ser,String ve) throws IOException {
|
||||
|
||||
|
||||
if (ve == null ){
|
||||
ve = request.getHeader("ve");
|
||||
if ( ve == null) {
|
||||
StaticLog.info("版本 为空");
|
||||
ve = "1.0";
|
||||
}
|
||||
}
|
||||
|
||||
// 获取客户端IP地址
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
|
||||
|
||||
|
||||
// 如果应用部署在反向代理或负载均衡器后面,可以通过X-Forwarded-For头部获取真实IP地址
|
||||
String forwardedFor = request.getHeader("X-Forwarded-For");
|
||||
if (forwardedFor != null && !forwardedFor.isEmpty()) {
|
||||
ipAddress = forwardedFor.split(",")[0];
|
||||
}
|
||||
StaticLog.info("收到服务器"+ipAddress+" 的getservicenew请求脚本 当前版本" + ve);
|
||||
|
||||
|
||||
|
||||
int[] intArray1 = new int[20];
|
||||
StringBuilder keys= new StringBuilder();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
intArray1[i]=(RandomUtil.randomInt(1, 9));
|
||||
keys.append(intArray1[i]);
|
||||
}
|
||||
|
||||
|
||||
//项目map
|
||||
Map<String, byte[]> stringStringMap=new HashMap<>();
|
||||
List<String> stringStringMapSX=new ArrayList<>();
|
||||
|
||||
|
||||
List<UserServerProject> getpro = userServerProjectService.getproAndOpen(ipAddress);
|
||||
|
||||
|
||||
if (getpro.isEmpty()) {
|
||||
|
||||
return ResponseEntity.ok("没有项目");
|
||||
|
||||
}else {
|
||||
|
||||
|
||||
|
||||
//从数据库找到所有的插件
|
||||
for (UserServerProject user2 : getpro) {
|
||||
String chajian = user2.getProjectName();
|
||||
if (jsonObject.get(ve) ==null){
|
||||
nut_sut(ve);
|
||||
System.out.println(jsonObject.get(ve));
|
||||
}
|
||||
|
||||
DPSScriptJson bean = jsonObject.get(ve).toBean(DPSScriptJson.class);
|
||||
DPSScriptJson.ProjectScriptItem projectScriptItem = bean.getProjectScript().get(chajian);
|
||||
if (projectScriptItem == null) {
|
||||
|
||||
StaticLog.info("版本" + ve);
|
||||
StaticLog.info("没有项目" + chajian);
|
||||
continue;
|
||||
}
|
||||
for (String s : projectScriptItem.getScript()) {
|
||||
|
||||
String s1 = fileManage.getFile() + "/DP-S_Script/Script"+ve+"/_DPS_" + "/_BuiltProject/" + s;
|
||||
|
||||
|
||||
File file2 = FileUtil.file(s1 );
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
stringStringMap.put(s1 , fileReader1.readString().getBytes());
|
||||
stringStringMapSX.add(s1 );
|
||||
|
||||
}
|
||||
StaticLog.info("加入" +chajian +"插件");
|
||||
|
||||
}
|
||||
|
||||
// File file2 = FileUtil.file(fileManage.getDpsScriptfile() + "user/通用/main.nut");
|
||||
// FileReader fileReader1 = new FileReader(file2);
|
||||
// stringStringMap.put(fileManage.getDpsScriptfile() + "user/通用/main.nut", fileReader1.readString().getBytes());
|
||||
// stringStringMapSX.add(fileManage.getDpsScriptfile() + "user/通用/main.nut");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//以下代码为从/root/rindro/dpsScript/user/ 目录中加载自定义的服务端脚本
|
||||
String s1 = fileManage.getDpsScriptfile() + "user/" + ipAddress;
|
||||
Path path = Paths.get(s1);
|
||||
if (Files.exists(path)) {
|
||||
List<String> strings444 = FileUtil.readUtf8Lines(s1 + "/config");
|
||||
for (String s : strings444) {
|
||||
File file2 = FileUtil.file(s1 + "/" + s);
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
stringStringMap.put(s1 + "/" + s, fileReader1.readString().getBytes());
|
||||
stringStringMapSX.add(s1 + "/" + s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 对通用文件进行加密处理
|
||||
for (Map.Entry<String, byte[]> entry : stringStringMap.entrySet()) {
|
||||
byte[] encryptedValue = RSATooL.Makecode(entry.getValue(), intArray1);
|
||||
entry.setValue(encryptedValue); // 直接在Map中更新值
|
||||
}
|
||||
|
||||
|
||||
|
||||
StringBuilder sb=new StringBuilder();
|
||||
for (String string : stringStringMapSX) {
|
||||
sb.append(string);
|
||||
sb.append("$$$$$");
|
||||
String string1 = Arrays.toString(stringStringMap.get(string));
|
||||
|
||||
sb.append(string1, 1, string1.length()-1);
|
||||
|
||||
sb.append("$$$$$");
|
||||
}
|
||||
|
||||
|
||||
String substring = sb.toString();
|
||||
StaticLog.info(ipAddress+"通过验证 返回dps nut脚本");
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
json.set("getBaseScriptStr",substring);
|
||||
json.set("key",RSATooL.encryption(keys.toString()));
|
||||
String string = json.toString();
|
||||
String compress = RSATooL.compress(string);
|
||||
|
||||
return ResponseEntity.ok(compress);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 递归遍历目录下所有文件(含所有层级子目录),返回最新修改时间
|
||||
* @param dir 要遍历的目录
|
||||
* @return 最新文件修改时间(毫秒级时间戳),无文件时返回 0
|
||||
*/
|
||||
private long traverseAllFiles(File dir) {
|
||||
long latestTime = 0;
|
||||
// 用原生 listFiles() 替代 FileUtil.ls,减少第三方依赖,同时处理 null 情况
|
||||
File[] files = dir.listFiles();
|
||||
if (files == null) {
|
||||
return latestTime; // 目录无权限访问或异常,返回当前最新时间
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
// 递归遍历子目录
|
||||
latestTime = Math.max(latestTime, traverseAllFiles(file));
|
||||
} else {
|
||||
// 对比文件修改时间,更新最新时间
|
||||
latestTime = Math.max(latestTime, file.lastModified());
|
||||
}
|
||||
}
|
||||
return latestTime;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// String decompress = RSATooL.encryption("https://dps-ma.senzo.online");
|
||||
// System.out.println(decompress);
|
||||
|
||||
System.out.println((3860+1730 -150-180-240-(40+37+94+20)) *0.7) ;
|
||||
|
||||
System.out.println(3380 -100 -381-850-60-50-100-400-100-40-150-250-175 -100);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import java.util.Collection;
|
||||
|
||||
@Getter
|
||||
public class AuthUser extends User {
|
||||
private final Integer userId;
|
||||
|
||||
public AuthUser(Integer userId, String username, String password, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(username, password, authorities);
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.api.IErrorCode;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CommonResult<T> {
|
||||
// 状态码
|
||||
private Integer code;
|
||||
// 提示信息
|
||||
private String message;
|
||||
// 返回的数据
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 成功返回结果
|
||||
*
|
||||
* @param data 返回的数据
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> success(T data) {
|
||||
return new CommonResult<>(200, "操作成功", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功返回结果并自定义提示信息
|
||||
*
|
||||
* @param data 返回的数据
|
||||
* @param message 提示信息
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> success(T data, String message) {
|
||||
return new CommonResult<>(200, message, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 失败返回结果并自定义提示信息
|
||||
*
|
||||
* @param message 提示信息
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(String message) {
|
||||
return new CommonResult<>(500, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
*
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> failed() {
|
||||
return failed(500, "操作失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败返回结果
|
||||
*
|
||||
* @param code 错误码
|
||||
* @param message 提示信息
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> failed(int code, String message) {
|
||||
return new CommonResult<>(code, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数验证失败返回结果
|
||||
*
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> validateFailed() {
|
||||
return failed(400, "参数验证失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数验证失败返回结果并自定义提示信息
|
||||
*
|
||||
* @param message 提示信息
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> validateFailed(String message) {
|
||||
return failed(400, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 未登录返回结果
|
||||
*
|
||||
* @param data 返回的数据
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> unauthorized(T data) {
|
||||
return new CommonResult<>(401, "暂未登录或 token 已经过期", data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 未授权返回结果
|
||||
*
|
||||
* @param data 返回的数据
|
||||
* @param <T> 数据类型
|
||||
* @return 通用返回对象
|
||||
*/
|
||||
public static <T> CommonResult<T> forbidden(T data) {
|
||||
return new CommonResult<>(403, "没有相关权限", data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@Data
|
||||
public class DPSScriptJson {
|
||||
|
||||
|
||||
private List<String> BaseScript;
|
||||
private Map<String, ProjectScriptItem> ProjectScript;
|
||||
|
||||
|
||||
@Data
|
||||
public static class ProjectScriptItem {
|
||||
private List<String> Script;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.example.sjkbf.entity.DTO;
|
||||
|
||||
import lombok.Data;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
public class LoginRequest {
|
||||
@NotBlank(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
@NotBlank(message = "密码不能为空")
|
||||
private String password;
|
||||
|
||||
@NotBlank(message = "验证qq不能为空")
|
||||
private String qq;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.sjkbf.entity.DTO;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class LoginResponse {
|
||||
private String token;
|
||||
private String username;
|
||||
private List<String> roles; // 权限/角色列表
|
||||
|
||||
public LoginResponse(String token, String username, List<String> roles) {
|
||||
this.token = token;
|
||||
this.username = username;
|
||||
this.roles = roles;
|
||||
}
|
||||
}
|
||||
34
旧的java项目/src/main/java/com/example/sjkbf/entity/Log.java
Normal file
34
旧的java项目/src/main/java/com/example/sjkbf/entity/Log.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-09-25
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Log implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
|
||||
private String name;
|
||||
|
||||
private String log;
|
||||
|
||||
private Integer type;
|
||||
//时间
|
||||
private Date time;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class ProjectPer implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@TableId
|
||||
private String projectName;
|
||||
|
||||
private String file;
|
||||
|
||||
private Integer permission;
|
||||
|
||||
private Integer demandGold;
|
||||
|
||||
}
|
||||
51
旧的java项目/src/main/java/com/example/sjkbf/entity/User.java
Normal file
51
旧的java项目/src/main/java/com/example/sjkbf/entity/User.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@TableName("sys_user")
|
||||
public class User implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
private Integer gold;
|
||||
|
||||
private String qq;
|
||||
|
||||
private String name;
|
||||
private String img;
|
||||
|
||||
private String clientKey;
|
||||
private String serverKey;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-17
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class UserAndServer implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String serverIp;
|
||||
|
||||
private String account;
|
||||
|
||||
private String password;
|
||||
|
||||
private String port;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.example.sjkbf.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-19
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class UserServerProject implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String serverIp;
|
||||
|
||||
private String projectName;
|
||||
|
||||
private Date expirationDate;
|
||||
|
||||
private String userName;
|
||||
|
||||
private int open;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.example.sjkbf.entity.projectconfig;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class Project {
|
||||
|
||||
String name;
|
||||
|
||||
List<String> Script;
|
||||
|
||||
|
||||
Map<String,Object> Info;
|
||||
|
||||
/**
|
||||
* 价格
|
||||
*/
|
||||
Integer price;
|
||||
|
||||
/**
|
||||
* 是否私有
|
||||
*/
|
||||
Boolean Private = false;
|
||||
/**
|
||||
* img路径
|
||||
*/
|
||||
String imgPath;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.sjkbf.entity.projectconfig;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class ProjectConfig {
|
||||
|
||||
private List<String> BaseScript;
|
||||
private List<String> CSBaseScript;
|
||||
|
||||
private Map<String, Project> ProjectScript = new HashMap<>();
|
||||
|
||||
|
||||
public List<String> BaseScriptStr = new ArrayList<>();
|
||||
public List<String> CSBaseScriptStr = new ArrayList<>();
|
||||
|
||||
public Map<String, List<String>> ProjectScriptStr = new HashMap<>();
|
||||
|
||||
//自定义脚本 key为ip v为自定义脚本
|
||||
public Map<String, List<String>> ProjectZDYScriptStr = new HashMap<>();
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.sjkbf.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.sjkbf.entity.Log;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-09-25
|
||||
*/
|
||||
@Mapper
|
||||
public interface LogMapper extends BaseMapper<Log> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.sjkbf.mapper;
|
||||
|
||||
import com.example.sjkbf.entity.ProjectPer;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
@Mapper()
|
||||
public interface ProjectPerMapper extends BaseMapper<ProjectPer> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.sjkbf.mapper;
|
||||
|
||||
import com.example.sjkbf.entity.UserAndServer;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-17
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserAndServerMapper extends BaseMapper<UserAndServer> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.sjkbf.mapper;
|
||||
|
||||
import com.example.sjkbf.entity.User;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.example.sjkbf.mapper;
|
||||
|
||||
import com.example.sjkbf.entity.UserServerProject;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-19
|
||||
*/
|
||||
@Mapper
|
||||
public interface UserServerProjectMapper extends BaseMapper<UserServerProject> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.example.sjkbf.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.example.sjkbf.entity.Log;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-09-25
|
||||
*/
|
||||
public interface LogService extends IService<Log> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.example.sjkbf.service;
|
||||
|
||||
import com.example.sjkbf.entity.ProjectPer;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.example.sjkbf.entity.projectconfig.Project;
|
||||
import com.example.sjkbf.entity.projectconfig.ProjectConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
public interface ProjectPerService extends IService<ProjectPer> {
|
||||
|
||||
/**
|
||||
* 根据项目名字获得项目信息
|
||||
* @param projectName
|
||||
* @return
|
||||
*/
|
||||
Project getByName(String projectName);
|
||||
|
||||
/**
|
||||
* 获得公开的插件项目信息
|
||||
* @return
|
||||
*/
|
||||
Map<String, Map<String, Object>> getProjectInfoList();
|
||||
|
||||
/**
|
||||
* 获得全部的插件项目信息
|
||||
* @return
|
||||
*/
|
||||
Map<String, Map<String, Object>> getProjectInfoListAll();
|
||||
|
||||
List<String> getBaseScriptStr( String ve);
|
||||
|
||||
/**
|
||||
* 获得base加密后的脚本
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
List<String> getBaseScriptStrEncrypt(int[] key,String ve);
|
||||
List<String> getCSBaseScriptStrEncrypt(int[] key,String ve);
|
||||
|
||||
List<String> getProjectScriptStr(String projectName,String ve);
|
||||
|
||||
/**
|
||||
* 获得项目加密后的脚本
|
||||
* @param projectName
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
List<String> getProjectScriptStrEncrypt(String projectName,int[] key,String ve);
|
||||
List<byte[]> getProjectScriptStrEncrypt2(String projectName,int[] key,String ve);
|
||||
|
||||
|
||||
/**
|
||||
* 获得项目购买所需积分
|
||||
* @param projectName
|
||||
* @return
|
||||
*/
|
||||
int getProjectPrice(String projectName);
|
||||
|
||||
List<byte[]> getBaseScriptStrEncrypt2(int[] key,String ve);
|
||||
|
||||
/**
|
||||
* 获得自定义脚本
|
||||
* @param ip
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
List<String> getzdy(String ip, int[] key,String ve);
|
||||
|
||||
/**
|
||||
* 获得没加密的自定义脚本
|
||||
* @param ip
|
||||
* @param ve
|
||||
* @return
|
||||
*/
|
||||
List<String> getzdy2(String ip,String ve);
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
package com.example.sjkbf.service;
|
||||
|
||||
import com.example.sjkbf.entity.UserAndServer;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户的服务器 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-17
|
||||
*/
|
||||
public interface UserAndServerService extends IService<UserAndServer> {
|
||||
|
||||
int selectCount(String ip, String userName);
|
||||
|
||||
List<UserAndServer> getServerList(String userName);
|
||||
|
||||
String updateServer(String ip, String userName, String account, String password, String port);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.example.sjkbf.service;
|
||||
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import cn.hutool.cache.impl.TimedCache;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.crypto.digest.DigestUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.example.sjkbf.util.MD5;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @Author l'amour solitaire
|
||||
* @Description 订单服务相关
|
||||
* @Date 2022/12/1 下午5:24
|
||||
**/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class UserOrderService {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
private final String payKey = "8658ea66fbbe4a1aad4691ddecefe5fa";
|
||||
|
||||
private final String payUrl = "https://2277883.pay.lanjingzf.com/createOrder?";
|
||||
|
||||
private static final String CREATE_PARAMS = "payId=%s&type=%s&price=%s&sign=%s&isHtml=1";
|
||||
|
||||
|
||||
|
||||
|
||||
public static TimedCache<String, Integer> timedCache = CacheUtil.newTimedCache(3000);
|
||||
|
||||
Map<String, Integer> orderIdAndPrice=new HashMap<>();
|
||||
|
||||
static {
|
||||
timedCache.schedulePrune(100);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param payType 【必传】微信支付传入1 支付宝支付传入2
|
||||
* @param price 【必传】订单金额
|
||||
* @Author l'amour solitaire
|
||||
* @Description 创建订单
|
||||
* @Date 2022/12/1 下午5:46
|
||||
**/
|
||||
public String create(Integer payType, int price,String name) throws IOException {
|
||||
|
||||
Integer i = timedCache.get(name);
|
||||
if (i==null) {
|
||||
timedCache.put(name, 1,5*60*1000);
|
||||
|
||||
}else {
|
||||
return "上次提交暂未结束,请稍后重试";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 创建订单 订单号为uid:时间戳
|
||||
String orderId = name + ":" + System.currentTimeMillis();
|
||||
|
||||
orderIdAndPrice.put(orderId,price);
|
||||
|
||||
String CREATE_PARAMS = "payId=%s&type=%d&price=%s&sign=%s&isHtml=1";
|
||||
|
||||
|
||||
String signSource = orderId + payType + price + payKey;
|
||||
String sign = DigestUtil.md5Hex(signSource);
|
||||
|
||||
String paramMap = String.format(CREATE_PARAMS, orderId, payType, price, sign);
|
||||
|
||||
HttpResponse execute = HttpRequest.get(payUrl+paramMap)
|
||||
// .header(Header.USER_AGENT, "Hutool http")//头信息,多个头信息多次调用此方法即可
|
||||
.timeout(20000)//超时,毫秒
|
||||
.execute();
|
||||
String body = execute.body();
|
||||
|
||||
|
||||
|
||||
// 返回支付页面地址,前端进行弹框展示即可
|
||||
return "https://2277883.pay.lanjingzf.com/"+extractBetweenQuotes(body);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付回调
|
||||
**/
|
||||
public String callback(String payId, String param, int type, double price, double reallyPrice, String sign) {
|
||||
Assert.isTrue(sign.equals(DigestUtil.md5Hex(payId + param + type + price + reallyPrice + payKey)), "非法请求!");
|
||||
System.out.println(payId);
|
||||
Integer i = orderIdAndPrice.get(payId);
|
||||
|
||||
System.out.println(orderIdAndPrice);
|
||||
if (i==null) {
|
||||
log.info("订单不存在");
|
||||
return "订单不存在";
|
||||
}
|
||||
if (i==-1){
|
||||
log.info("订单已处理");
|
||||
return "订单已处理";
|
||||
}
|
||||
|
||||
String[] split = payId.split(":");
|
||||
|
||||
|
||||
userService.addgold(split[0],i);
|
||||
log.info("订单支付成功");
|
||||
|
||||
timedCache.remove(split[0]);
|
||||
|
||||
orderIdAndPrice.put(payId,-1);
|
||||
|
||||
// 返回这个字符串,支付平台就知道回调接口成功了
|
||||
return "success";
|
||||
}
|
||||
|
||||
|
||||
public static String extractBetweenQuotes(String input) {
|
||||
// 检查输入是否为null
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 找到第一个单引号的位置
|
||||
int firstQuoteIndex = input.indexOf('\'');
|
||||
// 找到第二个单引号的位置(从第一个引号之后开始查找)
|
||||
int secondQuoteIndex = input.indexOf('\'', firstQuoteIndex + 1);
|
||||
|
||||
// 检查两个引号是否都存在且位置有效
|
||||
if (firstQuoteIndex != -1 && secondQuoteIndex != -1 && secondQuoteIndex > firstQuoteIndex) {
|
||||
// 提取两个引号之间的子字符串
|
||||
return input.substring(firstQuoteIndex + 1, secondQuoteIndex);
|
||||
}
|
||||
|
||||
// 如果未找到有效的引号对,返回null
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
int 毛收入=1890 +1381 +60+100+80+380 -50-30;//支付宝加微信加dps端收入
|
||||
int 净收入 = 毛收入 -245-20;//扣除服务器费用和会员费
|
||||
int 董收入= (int) (净收入*0.7);
|
||||
int 扣除dps端已经付给董的费用 = 董收入 -(60+100+80+380);
|
||||
int 最终结果 = 扣除dps端已经付给董的费用 - (1220 +100+ 3600 +95 +50); //1220为上月遗留 3600为贪玩账单 剩下的吃饭
|
||||
|
||||
|
||||
|
||||
System.out.println(最终结果);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.example.sjkbf.service;
|
||||
|
||||
import com.example.sjkbf.entity.UserServerProject;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户服务器插件 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-19
|
||||
*/
|
||||
public interface UserServerProjectService extends IService<UserServerProject> {
|
||||
|
||||
|
||||
/**
|
||||
* 给服务器添加或延长插件时间
|
||||
* @param ip 服务器ip
|
||||
* @param projectName 插件名字
|
||||
* @param time 时间
|
||||
* @param userName 用户名
|
||||
*/
|
||||
void addpro(String ip,String projectName,int time,String userName);
|
||||
|
||||
/**
|
||||
* 查询此服务器下的插件列表
|
||||
*/
|
||||
List<UserServerProject> getpro(String ip);
|
||||
|
||||
|
||||
/**
|
||||
* 查询这个服务器下开启的插件列表
|
||||
* @param ip
|
||||
* @return
|
||||
*/
|
||||
List<UserServerProject> getproAndOpen(String ip);
|
||||
|
||||
/**
|
||||
* 查询这个服务器下的插件
|
||||
* @param serverIp
|
||||
* @param projectName
|
||||
* @return
|
||||
*/
|
||||
UserServerProject getByIPAndName(String serverIp, String projectName);
|
||||
|
||||
/**
|
||||
* 查询这个账号下的所有插件
|
||||
*/
|
||||
List<UserServerProject> getByUserName(String userName);
|
||||
|
||||
String setproOpen(String ip, String projectName, String open, String userName);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.example.sjkbf.service;
|
||||
|
||||
import com.example.sjkbf.entity.DTO.LoginRequest;
|
||||
import com.example.sjkbf.entity.User;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
public interface UserService extends IService<User> {
|
||||
public boolean isUsernameExist(String username);
|
||||
|
||||
public void registerUser(LoginRequest request);
|
||||
|
||||
String buy(String ip, String projectName, String userName);
|
||||
|
||||
void updatePassword(LoginRequest request);
|
||||
|
||||
String addServer(String ip, String userName, String account, String password, String port);
|
||||
|
||||
String deleteServer(String ip, String userName);
|
||||
|
||||
String setKey(String userName, String clientkey, String serverkey);
|
||||
|
||||
String addgold(String userName, Integer gold);
|
||||
|
||||
String transfer(String myName, String username, Integer gold);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.example.sjkbf.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.example.sjkbf.mapper.LogMapper;
|
||||
import com.example.sjkbf.service.LogService;
|
||||
import com.example.sjkbf.entity.Log;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-09-25
|
||||
*/
|
||||
@Service
|
||||
public class LogServiceImpl extends ServiceImpl<LogMapper, Log> implements LogService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,388 @@
|
||||
package com.example.sjkbf.service.impl;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.example.sjkbf.common.FileManage;
|
||||
import com.example.sjkbf.entity.ProjectPer;
|
||||
import com.example.sjkbf.entity.projectconfig.Project;
|
||||
import com.example.sjkbf.entity.projectconfig.ProjectConfig;
|
||||
import com.example.sjkbf.mapper.ProjectPerMapper;
|
||||
import com.example.sjkbf.service.ProjectPerService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.example.sjkbf.util.RSATooL;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
@Service
|
||||
public class ProjectPerServiceImpl extends ServiceImpl<ProjectPerMapper, ProjectPer> implements ProjectPerService {
|
||||
|
||||
|
||||
@Autowired
|
||||
FileManage fileManage;
|
||||
|
||||
// public ProjectConfig projectConfig;
|
||||
|
||||
|
||||
//key为文件夹名字 y为json
|
||||
Map<String, ProjectConfig> projectScriptMap;
|
||||
|
||||
public String configMd5="";
|
||||
|
||||
@Override
|
||||
public Project getByName(String projectName) {
|
||||
|
||||
if (projectName != null){
|
||||
return projectScriptMap.get("max").getProjectScript().get(projectName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Map<String, Object>> getProjectInfoList() {
|
||||
|
||||
Map<String, Project> projectScript = projectScriptMap.get("max").getProjectScript();
|
||||
Set<String> strings = projectScript.keySet();
|
||||
|
||||
Map<String, Map<String, Object>> info = new HashMap<>();
|
||||
for (String string : strings) {
|
||||
//如果是私有的就不放进去
|
||||
if(projectScript.get(string).getPrivate())continue;
|
||||
|
||||
Map<String, Object> info1 = projectScript.get(string).getInfo();
|
||||
info1.put("ProjectPrice", projectScript.get(string).getPrice());
|
||||
info.put(string, info1);
|
||||
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Map<String, Object>> getProjectInfoListAll() {
|
||||
|
||||
Map<String, Project> projectScript = projectScriptMap.get("max").getProjectScript();
|
||||
Set<String> strings = projectScript.keySet();
|
||||
|
||||
Map<String, Map<String, Object>> info = new HashMap<>();
|
||||
for (String string : strings) {
|
||||
Map<String, Object> info1 = projectScript.get(string).getInfo();
|
||||
info1.put("ProjectPrice", projectScript.get(string).getPrice());
|
||||
info.put(string, info1);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得所有的base脚本
|
||||
* 需要一个版本号
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getBaseScriptStr(String ve) {
|
||||
return projectScriptMap.get(ve).getBaseScriptStr();
|
||||
}
|
||||
|
||||
public List<String> getCSBaseScriptStr(String ve) {
|
||||
return projectScriptMap.get(ve).getCSBaseScriptStr();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key对base脚本进行加密
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> getBaseScriptStrEncrypt(int[] key,String ve) {
|
||||
List<String> baseScriptStr = getBaseScriptStr(ve);
|
||||
List<String> StrEncrypt = new ArrayList<>();
|
||||
|
||||
for (String s : baseScriptStr) {
|
||||
byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
|
||||
|
||||
String string = Arrays.toString(makecode);
|
||||
StrEncrypt.add(string.substring(1, string.length()-1));
|
||||
|
||||
}
|
||||
return StrEncrypt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getCSBaseScriptStrEncrypt(int[] key,String ve) {
|
||||
List<String> baseScriptStr = getCSBaseScriptStr(ve);
|
||||
List<String> StrEncrypt = new ArrayList<>();
|
||||
|
||||
for (String s : baseScriptStr) {
|
||||
byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
|
||||
|
||||
String string = Arrays.toString(makecode);
|
||||
StrEncrypt.add(string.substring(1, string.length()-1));
|
||||
|
||||
}
|
||||
return StrEncrypt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据key对base脚本进行加密
|
||||
*
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public List<byte[]> getBaseScriptStrEncrypt2(int[] key,String ve) {
|
||||
List<String> baseScriptStr = getBaseScriptStr(ve);
|
||||
List<byte[]> StrEncrypt = new ArrayList<>();
|
||||
|
||||
for (String s : baseScriptStr) {
|
||||
|
||||
byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
|
||||
|
||||
String string = Arrays.toString(makecode);
|
||||
StrEncrypt.add(makecode);
|
||||
}
|
||||
return StrEncrypt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getzdy(String ip, int[] key,String ve) {
|
||||
|
||||
Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectZDYScriptStr();
|
||||
if (projectScriptStr==null)return new ArrayList<>();
|
||||
List<String> strings = projectScriptStr.get(ip);
|
||||
if (strings==null)return new ArrayList<>();
|
||||
|
||||
List<String> StrEncrypt = new ArrayList<>();
|
||||
for (String s : strings) {
|
||||
byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
|
||||
String string = Arrays.toString(makecode);
|
||||
StrEncrypt.add(string.substring(1, string.length()-1));
|
||||
}
|
||||
return StrEncrypt;
|
||||
}
|
||||
|
||||
|
||||
byte[] AESkey = new byte[]{120, -2, 20, -80, -24, 60, 62, -48, -18, 101, -117, -8, 52, 48, -59, 94};
|
||||
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, AESkey);
|
||||
|
||||
@Override
|
||||
public List<String> getzdy2(String ip,String ve) {
|
||||
ve = "max";
|
||||
Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectZDYScriptStr();
|
||||
if (projectScriptStr==null)return new ArrayList<>();
|
||||
List<String> strings = projectScriptStr.get(ip);
|
||||
if (strings==null)return new ArrayList<>();
|
||||
|
||||
List<String> StrEncrypt = new ArrayList<>();
|
||||
for (String s : strings) {
|
||||
|
||||
//加密为16进制表示
|
||||
String encryptHex = aes.encryptHex(s);
|
||||
StrEncrypt.add(encryptHex);
|
||||
}
|
||||
return StrEncrypt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> getProjectScriptStr(String projectName,String ve) {
|
||||
List<String> strings = projectScriptMap.get(ve).getProjectScriptStr().get(projectName);
|
||||
return strings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> getProjectScriptStrEncrypt(String projectName,int[] key,String ve) {
|
||||
Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectScriptStr();
|
||||
if (projectScriptStr==null)return new ArrayList<>();
|
||||
List<String> strings = projectScriptStr.get(projectName);
|
||||
List<String> StrEncrypt = new ArrayList<>();
|
||||
for (String s : strings) {
|
||||
byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
|
||||
String string = Arrays.toString(makecode);
|
||||
StrEncrypt.add(string.substring(1, string.length()-1));
|
||||
}
|
||||
return StrEncrypt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<byte[]> getProjectScriptStrEncrypt2(String projectName,int[] key,String ve) {
|
||||
Map<String, List<String>> projectScriptStr = projectScriptMap.get(ve).getProjectScriptStr();
|
||||
if (projectScriptStr==null)return new ArrayList<>();
|
||||
List<String> strings = projectScriptStr.get(projectName);
|
||||
List<byte[]> StrEncrypt = new ArrayList<>();
|
||||
for (String s : strings) {
|
||||
byte[] makecode = RSATooL.Makecode(s.getBytes(), key);
|
||||
String string = Arrays.toString(makecode);
|
||||
StrEncrypt.add(makecode);
|
||||
}
|
||||
return StrEncrypt;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getProjectPrice(String projectName) {
|
||||
if (projectScriptMap.get("max").getProjectScript().get(projectName)!=null){
|
||||
return projectScriptMap.get("max").getProjectScript().get(projectName).getPrice();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void initInfo(){
|
||||
projectScriptMap = new HashMap<>();
|
||||
System.out.println("初始化项目信息");
|
||||
|
||||
String scriptfile = fileManage.getScriptfile();
|
||||
//获得这个文件夹下的所有子文件夹
|
||||
File[] files = FileUtil.ls(scriptfile);
|
||||
|
||||
File[] subDirs = Arrays.stream(files)
|
||||
.filter(File::isDirectory) // 仅保留子文件夹
|
||||
.toArray(File[]::new);
|
||||
|
||||
// 2. 使用自定义自然排序比较器排序
|
||||
Arrays.sort(subDirs, new NaturalNameComparator());
|
||||
|
||||
for (File file : subDirs) {
|
||||
//取Script 之后的文件名
|
||||
String name = file.getName().substring(7);
|
||||
System.out.println( name);
|
||||
ProjectConfig projectConfig = initInfo(file.getPath());
|
||||
projectScriptMap.put(name, projectConfig);
|
||||
projectScriptMap.put("max", projectConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String content = "test中文";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//读取文件
|
||||
public synchronized ProjectConfig initInfo( String path) {
|
||||
FileReader fileReader = new FileReader(path+"/"+"FileConfig.json");
|
||||
String result = fileReader.readString();
|
||||
ProjectConfig projectConfig = JSONUtil.toBean(result, new TypeReference<ProjectConfig>() {}, true);
|
||||
|
||||
List<String> baseScript = projectConfig.getBaseScript();
|
||||
|
||||
|
||||
for (String s : baseScript) {
|
||||
FileReader fileReader1 = new FileReader(path+"/"+s);
|
||||
projectConfig.getBaseScriptStr().add(fileReader1.readString());
|
||||
}
|
||||
|
||||
/*
|
||||
List<String> csBaseScript = projectConfig.getCSBaseScript();
|
||||
for (String s : csBaseScript) {
|
||||
FileReader fileReader1 = new FileReader(path+"/"+s);
|
||||
projectConfig.getCSBaseScriptStr().add(fileReader1.readString());
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
Set<String> strings = projectConfig.getProjectScript().keySet();
|
||||
|
||||
for (String string : strings) {
|
||||
|
||||
List<String> script = projectConfig.getProjectScript().get(string).getScript();
|
||||
projectConfig.getProjectScriptStr().put(string,new ArrayList<>());
|
||||
for (String s : script) {
|
||||
FileReader fileReader1 = new FileReader(path+"\\"+s);
|
||||
projectConfig.getProjectScriptStr().get(string).add(fileReader1.readString());
|
||||
}
|
||||
}
|
||||
|
||||
File[] ls = FileUtil.ls("/root/rindro/ClentUserScript");
|
||||
|
||||
for (File l : ls) {
|
||||
Path path1 = Paths.get(l.getPath());
|
||||
List<String> ZDYScript = new ArrayList<>();
|
||||
if (Files.exists(path1)) {
|
||||
List<String> strings444 = FileUtil.readUtf8Lines(l + "/config");
|
||||
for (String s : strings444) {
|
||||
File file2 = FileUtil.file(l + "/" + s);
|
||||
FileReader fileReader1 = new FileReader(file2);
|
||||
ZDYScript.add(fileReader1.readString());
|
||||
}
|
||||
}
|
||||
projectConfig.getProjectZDYScriptStr().put(l.getName(),ZDYScript);
|
||||
}
|
||||
|
||||
|
||||
return projectConfig;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static final Pattern NUMBER_PATTERN = Pattern.compile("(\\d+\\.?\\d*)|([^\\d]+)");
|
||||
|
||||
|
||||
// 自定义自然排序比较器(核心)
|
||||
static class NaturalNameComparator implements Comparator<File> {
|
||||
@Override
|
||||
public int compare(File f1, File f2) {
|
||||
String name1 = f1.getName();
|
||||
String name2 = f2.getName();
|
||||
|
||||
// 拆分两个名称的数字/非数字片段,逐个比较
|
||||
Matcher m1 = NUMBER_PATTERN.matcher(name1);
|
||||
Matcher m2 = NUMBER_PATTERN.matcher(name2);
|
||||
|
||||
while (m1.find() && m2.find()) {
|
||||
String segment1 = m1.group();
|
||||
String segment2 = m2.group();
|
||||
|
||||
int compareResult;
|
||||
// 判断当前片段是否是数字
|
||||
if (segment1.matches("\\d+\\.?\\d*") && segment2.matches("\\d+\\.?\\d*")) {
|
||||
// 数字片段:按数值大小比较(支持小数)
|
||||
double num1 = Double.parseDouble(segment1);
|
||||
double num2 = Double.parseDouble(segment2);
|
||||
compareResult = Double.compare(num1, num2);
|
||||
} else {
|
||||
// 非数字片段:按字符串字典序比较(忽略大小写,可选)
|
||||
compareResult = segment1.compareToIgnoreCase(segment2);
|
||||
}
|
||||
|
||||
// 只要有一个片段比较出结果,就返回
|
||||
if (compareResult != 0) {
|
||||
return compareResult;
|
||||
}
|
||||
}
|
||||
|
||||
// 前面的片段都相同,短名称排前面
|
||||
return Integer.compare(name1.length(), name2.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.example.sjkbf.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.sjkbf.entity.UserAndServer;
|
||||
import com.example.sjkbf.mapper.UserAndServerMapper;
|
||||
import com.example.sjkbf.service.UserAndServerService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-17
|
||||
*/
|
||||
@Service
|
||||
public class UserAndServerServiceImpl extends ServiceImpl<UserAndServerMapper, UserAndServer> implements UserAndServerService {
|
||||
|
||||
@Autowired
|
||||
private UserAndServerMapper userAndServerMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public int selectCount(String ip, String userName) {
|
||||
|
||||
return userAndServerMapper.selectCount(new QueryWrapper<UserAndServer>().eq("server_ip",ip).eq("user_name",userName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserAndServer> getServerList(String userName) {
|
||||
|
||||
List<UserAndServer> userName1 = list(new QueryWrapper<UserAndServer>().eq("user_name", userName));
|
||||
|
||||
return userName1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String updateServer(String ip, String userName, String account, String password, String port) {
|
||||
UserAndServer one = getOne(new QueryWrapper<UserAndServer>().eq("server_ip", ip).eq("user_name", userName));
|
||||
if (one != null){
|
||||
one.setAccount(account);
|
||||
one.setPassword(password);
|
||||
one.setPort(port);
|
||||
return updateById(one)?"修改成功":"修改失败";
|
||||
}
|
||||
|
||||
return "服务器不存在";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.example.sjkbf.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.sjkbf.entity.AuthUser;
|
||||
import com.example.sjkbf.entity.User;
|
||||
import com.example.sjkbf.mapper.UserMapper;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
*用户认证类
|
||||
*/
|
||||
@Service
|
||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
|
||||
// 构造器注入(推荐)
|
||||
public UserDetailsServiceImpl(UserMapper userMapper) {
|
||||
this.userMapper = userMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
User user = null;
|
||||
try {
|
||||
|
||||
// 1. 查询数据库
|
||||
user= userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 2. 用户不存在
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("用户不存在");
|
||||
}
|
||||
|
||||
// 3. 转换为 Spring Security 的 UserDetails 对象
|
||||
return new AuthUser(
|
||||
user.getId(),
|
||||
user.getUsername(),
|
||||
user.getPassword(),
|
||||
AuthorityUtils.createAuthorityList("ROLE_ALL") // 假设 roles 字段存储如 "ROLE_ADMIN,ROLE_USER"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.example.sjkbf.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.sjkbf.entity.UserServerProject;
|
||||
import com.example.sjkbf.mapper.UserServerProjectMapper;
|
||||
import com.example.sjkbf.service.UserServerProjectService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-19
|
||||
*/
|
||||
@Service
|
||||
public class UserServerProjectServiceImpl extends ServiceImpl<UserServerProjectMapper, UserServerProject> implements UserServerProjectService {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addpro(String ip, String name, int time, String userName) {
|
||||
UserServerProject one = getOne(new QueryWrapper<UserServerProject>().eq("server_ip", ip).eq("project_name", name));
|
||||
if (one==null){
|
||||
UserServerProject userServerProject = new UserServerProject();
|
||||
userServerProject.setServerIp(ip);
|
||||
userServerProject.setProjectName(name);
|
||||
userServerProject.setUserName(userName);
|
||||
userServerProject.setOpen(1);
|
||||
DateTime date = DateUtil.date();
|
||||
DateTime newDate2 = DateUtil.offsetDay(date, time);
|
||||
userServerProject.setExpirationDate(newDate2);
|
||||
save(userServerProject);
|
||||
}else {
|
||||
Date expirationDate = one.getExpirationDate();
|
||||
DateTime newDate2 = DateUtil.offsetDay(expirationDate, time);
|
||||
one.setExpirationDate(newDate2);
|
||||
update(one, new QueryWrapper<UserServerProject>().eq("server_ip", ip).eq("project_name", name));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserServerProject> getpro(String ip) {
|
||||
|
||||
List<UserServerProject> list = list(new QueryWrapper<UserServerProject>().eq("server_ip", ip).ge("expiration_date", DateUtil.date()));
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserServerProject> getproAndOpen(String ip) {
|
||||
|
||||
List<UserServerProject> list = list(new QueryWrapper<UserServerProject>().eq("server_ip", ip).eq("open", 1).ge("expiration_date", DateUtil.date()));
|
||||
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserServerProject getByIPAndName(String serverIp, String projectName) {
|
||||
|
||||
return getOne(new QueryWrapper<UserServerProject>().eq("server_ip", serverIp).eq("project_name", projectName).ge("expiration_date", DateUtil.date()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserServerProject> getByUserName(String userName) {
|
||||
|
||||
return list(new QueryWrapper<UserServerProject>().eq("user_name", userName).ge("expiration_date", DateUtil.date()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String setproOpen(String ip, String projectName, String open, String userName) {
|
||||
UserServerProject one = getOne(new QueryWrapper<UserServerProject>().eq("server_ip", ip).eq("project_name", projectName));
|
||||
if (one!=null){
|
||||
one.setOpen(Integer.parseInt(open));
|
||||
update(one, new QueryWrapper<UserServerProject>().eq("server_ip", ip).eq("project_name", projectName));
|
||||
return "操作成功";
|
||||
}else {
|
||||
return "账号下不存在此项目,请检查项目所有权是否为该账号";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
package com.example.sjkbf.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.file.FileWriter;
|
||||
import cn.hutool.log.StaticLog;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.example.sjkbf.common.FileManage;
|
||||
import com.example.sjkbf.controller.verifyController;
|
||||
import com.example.sjkbf.entity.DTO.LoginRequest;
|
||||
import com.example.sjkbf.entity.Log;
|
||||
import com.example.sjkbf.entity.ProjectPer;
|
||||
import com.example.sjkbf.entity.User;
|
||||
import com.example.sjkbf.entity.UserAndServer;
|
||||
import com.example.sjkbf.entity.projectconfig.Project;
|
||||
import com.example.sjkbf.mapper.UserMapper;
|
||||
import com.example.sjkbf.service.*;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author bozhiqiang
|
||||
* @since 2025-04-15
|
||||
*/
|
||||
@Service
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Autowired
|
||||
private ProjectPerService projectPerService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserAndServerService userAndServerService;
|
||||
|
||||
@Autowired
|
||||
private UserServerProjectService userServerProjectService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private LogService logService;
|
||||
|
||||
@Autowired
|
||||
FileManage fileManage;
|
||||
// 检查用户名是否存在
|
||||
public boolean isUsernameExist(String username) {
|
||||
return userMapper.selectCount(new QueryWrapper<User>().eq("username", username)) > 0;
|
||||
}
|
||||
|
||||
|
||||
// 注册用户
|
||||
public void registerUser(LoginRequest request) {
|
||||
User user = new User();
|
||||
user.setUsername(request.getUsername());
|
||||
user.setPassword(passwordEncoder.encode(request.getPassword())); // 密码加密
|
||||
user.setQq(request.getQq());
|
||||
user.setGold(0);
|
||||
user.setName(generateRandomString());
|
||||
save(user);
|
||||
}
|
||||
public static String generateRandomString() {
|
||||
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
Random random = new Random();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int index = random.nextInt(characters.length());
|
||||
sb.append(characters.charAt(index));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional//开启事务 保证同时成功或者失败
|
||||
public String buy(String ip, String projectName, String userName) {
|
||||
//获得插件项目信息
|
||||
Project byName = projectPerService.getByName(projectName);
|
||||
if (byName==null)return "查询不到该插件项目";
|
||||
if (userAndServerService.selectCount(ip, userName)==0){
|
||||
return "账号下不存在此服务器";
|
||||
}
|
||||
|
||||
|
||||
User username = getOne(new QueryWrapper<User>().eq("username", userName));
|
||||
|
||||
int demandGold = projectPerService.getProjectPrice(projectName);
|
||||
if (demandGold>0) {
|
||||
StaticLog.info("用户:"+userName+"购买项目:"+projectName+" IP:"+userName);
|
||||
//扣减金币
|
||||
if (username.getGold() < demandGold){
|
||||
StaticLog.info("用户:"+userName+"购买项目:"+projectName+" IP:"+userName+"积分不足");
|
||||
return "积分不足";
|
||||
}
|
||||
username.setGold(username.getGold() - demandGold);
|
||||
updateById(username);
|
||||
|
||||
verifyController.ipAndMac.remove( ip);
|
||||
}
|
||||
// 这里还要对服务器脚本数据库进行添加
|
||||
userServerProjectService.addpro(ip, projectName, 31, userName);
|
||||
|
||||
try {
|
||||
FileWriter writer = new FileWriter("/root/java/"+"log.txt");
|
||||
String now = DateUtil.now();
|
||||
writer.append(now + "用户:"+userName+"购买项目:"+projectName+" IP:"+userName +"购买完成");
|
||||
|
||||
Log log1 = new Log();
|
||||
log1.setName(userName);
|
||||
log1.setLog("购买项目:"+projectName+" IP:"+ip +"购买完成,花费积分"+ demandGold);
|
||||
|
||||
if (demandGold>0){
|
||||
log1.setType(3);
|
||||
}else {
|
||||
log1.setType(2);
|
||||
}
|
||||
|
||||
log1.setTime(DateUtil.date());
|
||||
logService.save(log1);
|
||||
}catch (Exception e){
|
||||
StaticLog.info("用户:"+userName+"购买项目:"+projectName+" IP:"+userName+"写入日志失败");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return "购买成功";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePassword(LoginRequest request) {
|
||||
String username = request.getUsername();
|
||||
User username1 = getOne(new QueryWrapper<User>().eq("username", username));
|
||||
|
||||
if (username1!=null && Objects.equals(request.getQq(), username1.getQq())){
|
||||
username1.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||
updateById(username1);
|
||||
}else {
|
||||
throw new RuntimeException("验证信息错误");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addServer(String ip, String userName, String account, String password, String port) {
|
||||
// if (userAndServerService.selectCount(ip, userName)>0){
|
||||
// return "该服务器已存在,请不要重复添加";
|
||||
// }
|
||||
|
||||
UserAndServer one = userAndServerService.getOne(new QueryWrapper<UserAndServer>().eq("server_ip", ip).eq("user_name", userName));
|
||||
if (one!=null){
|
||||
one.setAccount(account);
|
||||
one.setPassword(password);
|
||||
one.setPort(port);
|
||||
|
||||
userAndServerService.update(one, new QueryWrapper<UserAndServer>().eq("server_ip", ip).eq("user_name", userName));
|
||||
|
||||
}else {
|
||||
UserAndServer userAndServer = new UserAndServer();
|
||||
userAndServer.setUserName(userName);
|
||||
userAndServer.setServerIp(ip);
|
||||
userAndServer.setAccount(account);
|
||||
userAndServer.setPassword(password);
|
||||
userAndServer.setPort(port);
|
||||
userAndServerService.save(userAndServer);
|
||||
}
|
||||
|
||||
return "添加成功";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deleteServer(String ip, String userName) {
|
||||
if (userAndServerService.selectCount(ip, userName)>0){
|
||||
userAndServerService.remove(new QueryWrapper<UserAndServer>().eq("server_ip", ip).eq("user_name", userName));
|
||||
return "删除成功";
|
||||
}
|
||||
return "删除失败";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String setKey(String userName, String clientkey, String serverkey) {
|
||||
User username = getOne(new QueryWrapper<User>().eq("username", userName));
|
||||
if (username!=null){
|
||||
if (clientkey!=null) {
|
||||
username.setClientKey(clientkey);
|
||||
}
|
||||
if (serverkey!=null) {
|
||||
username.setServerKey(serverkey);
|
||||
}
|
||||
updateById(username);
|
||||
return "设置成功";
|
||||
}
|
||||
|
||||
|
||||
return "设置 请重新登录后再试";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addgold(String userName, Integer gold) {
|
||||
|
||||
User username = getOne(new QueryWrapper<User>().eq("username", userName));
|
||||
if (gold == 200){
|
||||
gold= 220;
|
||||
}
|
||||
if (gold == 500){
|
||||
gold= 570;
|
||||
}
|
||||
|
||||
if (username!=null){
|
||||
username.setGold(username.getGold()+gold);
|
||||
updateById(username);
|
||||
//记录日志
|
||||
FileWriter writer = new FileWriter(fileManage.getFile()+"log.txt");
|
||||
String now = DateUtil.now();
|
||||
writer.append(now+ ":"+userName+"充值"+gold+"成功\r\n");
|
||||
Log log1 = new Log();
|
||||
log1.setName(userName);
|
||||
log1.setLog("充值"+gold+"成功");
|
||||
log1.setType(1);
|
||||
log1.setTime(DateUtil.date());
|
||||
logService.save(log1);
|
||||
|
||||
|
||||
return "充值成功";
|
||||
}
|
||||
return "充值失败";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public String transfer(String myName, String username, Integer gold) {
|
||||
// 按固定顺序锁定账户,避免死锁
|
||||
String firstLock = myName.compareTo(username) < 0 ? myName : username;
|
||||
String secondLock = myName.compareTo(username) < 0 ? username : myName;
|
||||
|
||||
// 使用for update锁定账户
|
||||
User firstUser = getOne(new QueryWrapper<User>()
|
||||
.eq("username", firstLock)
|
||||
.last("for update"));
|
||||
|
||||
User secondUser = getOne(new QueryWrapper<User>()
|
||||
.eq("username", secondLock)
|
||||
.last("for update"));
|
||||
|
||||
// 由于锁定顺序固定,我们需要根据实际转账方向确定哪个是转出账户,哪个是转入账户
|
||||
User myUser = firstLock.equals(myName) ? firstUser : secondUser;
|
||||
User targetUser = firstLock.equals(myName) ? secondUser : firstUser;
|
||||
|
||||
if (targetUser == null) {
|
||||
return "被转让用户不存在,请检查用户名";
|
||||
}
|
||||
|
||||
if (myUser.getGold() < gold) {
|
||||
return "余额不足";
|
||||
}
|
||||
|
||||
// 更新余额
|
||||
myUser.setGold(myUser.getGold() - gold);
|
||||
updateById(myUser);
|
||||
|
||||
targetUser.setGold(targetUser.getGold() + gold);
|
||||
updateById(targetUser);
|
||||
|
||||
// 记录日志
|
||||
Log log1 = new Log();
|
||||
log1.setName(myName);
|
||||
log1.setLog(myName + "向" + username + "转让" + gold + "积分");
|
||||
log1.setType(4);
|
||||
log1.setTime(DateUtil.date());
|
||||
logService.save(log1);
|
||||
|
||||
return "转让完毕";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
package com.example.sjkbf.util;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.media.Media;
|
||||
import javafx.scene.media.MediaPlayer;
|
||||
import javafx.scene.media.MediaView;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* JavaFX视频播放器 - 用于测试服务端视频流
|
||||
*/
|
||||
public class JavaFXVideoPlayer extends Application {
|
||||
|
||||
private MediaPlayer mediaPlayer;
|
||||
private MediaView mediaView;
|
||||
private Label statusLabel;
|
||||
private ProgressBar progressBar;
|
||||
private TextField projectField;
|
||||
private TextField videoNameField;
|
||||
private TextField serverUrlField;
|
||||
private Button playButton;
|
||||
private Button pauseButton;
|
||||
private Button stopButton;
|
||||
private Slider volumeSlider;
|
||||
private Slider seekSlider;
|
||||
private DoubleProperty playbackRate;
|
||||
|
||||
private static final String DEFAULT_SERVER = "http://localhost:8651";
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) {
|
||||
playbackRate = new SimpleDoubleProperty(1.0);
|
||||
|
||||
// 创建UI组件
|
||||
createUIComponents();
|
||||
|
||||
// 布局
|
||||
VBox root = createLayout();
|
||||
|
||||
// 场景
|
||||
Scene scene = new Scene(root, 1000, 700);
|
||||
scene.getStylesheets().add(getClass().getResource("/styles.css").toExternalForm());
|
||||
|
||||
// 舞台设置
|
||||
primaryStage.setTitle("视频流测试播放器");
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.setOnCloseRequest(event -> cleanup());
|
||||
primaryStage.show();
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
// 输入字段
|
||||
serverUrlField = new TextField(DEFAULT_SERVER);
|
||||
serverUrlField.setPromptText("服务器地址");
|
||||
|
||||
projectField = new TextField("战令");
|
||||
projectField.setPromptText("项目名称");
|
||||
|
||||
videoNameField = new TextField("2");
|
||||
videoNameField.setPromptText("视频名称");
|
||||
|
||||
// 控制按钮
|
||||
playButton = new Button("播放");
|
||||
playButton.setOnAction(e -> playVideo());
|
||||
|
||||
pauseButton = new Button("暂停");
|
||||
pauseButton.setOnAction(e -> pauseVideo());
|
||||
pauseButton.setDisable(true);
|
||||
|
||||
stopButton = new Button("停止");
|
||||
stopButton.setOnAction(e -> stopVideo());
|
||||
stopButton.setDisable(true);
|
||||
|
||||
// 媒体视图
|
||||
mediaView = new MediaView();
|
||||
mediaView.setFitWidth(800);
|
||||
mediaView.setFitHeight(450);
|
||||
mediaView.setPreserveRatio(true);
|
||||
|
||||
// 进度条和滑块
|
||||
progressBar = new ProgressBar(0);
|
||||
progressBar.setPrefWidth(800);
|
||||
|
||||
seekSlider = new Slider(0, 100, 0);
|
||||
seekSlider.setPrefWidth(800);
|
||||
seekSlider.valueProperty().addListener((obs, oldVal, newVal) -> {
|
||||
if (seekSlider.isValueChanging() && mediaPlayer != null) {
|
||||
Duration duration = mediaPlayer.getTotalDuration();
|
||||
if (duration != null) {
|
||||
mediaPlayer.seek(duration.multiply(newVal.doubleValue() / 100.0));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 音量控制
|
||||
volumeSlider = new Slider(0, 100, 50);
|
||||
volumeSlider.setPrefWidth(150);
|
||||
volumeSlider.valueProperty().addListener((obs, oldVal, newVal) -> {
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.setVolume(newVal.doubleValue() / 100.0);
|
||||
}
|
||||
});
|
||||
|
||||
// 状态标签
|
||||
statusLabel = new Label("准备就绪");
|
||||
statusLabel.setStyle("-fx-text-fill: #2E8B57; -fx-font-weight: bold;");
|
||||
}
|
||||
|
||||
private VBox createLayout() {
|
||||
VBox root = new VBox(15);
|
||||
root.setPadding(new Insets(15));
|
||||
root.setStyle("-fx-background-color: #2F4F4F;");
|
||||
|
||||
// 标题
|
||||
Label titleLabel = new Label("服务端视频流测试播放器");
|
||||
titleLabel.setStyle("-fx-text-fill: white; -fx-font-size: 20px; -fx-font-weight: bold;");
|
||||
|
||||
// 输入区域
|
||||
GridPane inputGrid = new GridPane();
|
||||
inputGrid.setHgap(10);
|
||||
inputGrid.setVgap(10);
|
||||
inputGrid.setPadding(new Insets(10));
|
||||
inputGrid.setStyle("-fx-background-color: #556B2F; -fx-background-radius: 5;");
|
||||
|
||||
inputGrid.add(new Label("服务器:"), 0, 0);
|
||||
inputGrid.add(serverUrlField, 1, 0);
|
||||
inputGrid.add(new Label("项目:"), 0, 1);
|
||||
inputGrid.add(projectField, 1, 1);
|
||||
inputGrid.add(new Label("视频:"), 0, 2);
|
||||
inputGrid.add(videoNameField, 1, 2);
|
||||
|
||||
serverUrlField.setPrefWidth(300);
|
||||
projectField.setPrefWidth(200);
|
||||
videoNameField.setPrefWidth(200);
|
||||
|
||||
// 控制按钮区域
|
||||
HBox controlBox = new HBox(10);
|
||||
controlBox.setAlignment(Pos.CENTER);
|
||||
controlBox.getChildren().addAll(playButton, pauseButton, stopButton);
|
||||
|
||||
// 音量控制
|
||||
HBox volumeBox = new HBox(10);
|
||||
volumeBox.setAlignment(Pos.CENTER_LEFT);
|
||||
volumeBox.getChildren().addAll(new Label("音量:"), volumeSlider);
|
||||
|
||||
// 播放速率控制
|
||||
HBox rateBox = new HBox(10);
|
||||
rateBox.setAlignment(Pos.CENTER_LEFT);
|
||||
ComboBox<String> rateCombo = new ComboBox<>();
|
||||
rateCombo.getItems().addAll("0.5x", "1.0x", "1.5x", "2.0x");
|
||||
rateCombo.setValue("1.0x");
|
||||
rateCombo.setOnAction(e -> {
|
||||
String selected = rateCombo.getValue();
|
||||
double rate = Double.parseDouble(selected.replace("x", ""));
|
||||
playbackRate.set(rate);
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.setRate(rate);
|
||||
}
|
||||
});
|
||||
rateBox.getChildren().addAll(new Label("播放速度:"), rateCombo);
|
||||
|
||||
// 状态区域
|
||||
HBox statusBox = new HBox(10);
|
||||
statusBox.setAlignment(Pos.CENTER);
|
||||
statusBox.getChildren().addAll(statusLabel, progressBar);
|
||||
|
||||
// 组装所有组件
|
||||
root.getChildren().addAll(
|
||||
titleLabel,
|
||||
inputGrid,
|
||||
controlBox,
|
||||
new Separator(),
|
||||
mediaView,
|
||||
new Label("播放进度:"),
|
||||
seekSlider,
|
||||
new Separator(),
|
||||
volumeBox,
|
||||
rateBox,
|
||||
statusBox
|
||||
);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void playVideo() {
|
||||
try {
|
||||
String serverUrl = serverUrlField.getText().trim();
|
||||
String project = projectField.getText().trim();
|
||||
String videoName = videoNameField.getText().trim();
|
||||
|
||||
if (project.isEmpty() || videoName.isEmpty()) {
|
||||
showError("请填写项目名称和视频名称");
|
||||
return;
|
||||
}
|
||||
|
||||
// 编码URL参数
|
||||
String encodedProject = URLEncoder.encode(project, StandardCharsets.UTF_8.toString());
|
||||
String encodedVideoName = URLEncoder.encode(videoName, StandardCharsets.UTF_8.toString());
|
||||
|
||||
String videoUrl = String.format("%s/api/videos/%s/%s",
|
||||
serverUrl, encodedProject, encodedVideoName);
|
||||
|
||||
updateStatus("正在连接: " + videoUrl);
|
||||
|
||||
// 清理之前的播放器
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.dispose();
|
||||
}
|
||||
|
||||
// 创建新的媒体播放器
|
||||
Media media = new Media(videoUrl);
|
||||
mediaPlayer = new MediaPlayer(media);
|
||||
mediaView.setMediaPlayer(mediaPlayer);
|
||||
|
||||
// 设置播放速率
|
||||
mediaPlayer.setRate(playbackRate.get());
|
||||
mediaPlayer.setVolume(volumeSlider.getValue() / 100.0);
|
||||
|
||||
// 设置事件监听器
|
||||
setupMediaListeners();
|
||||
|
||||
// 开始播放
|
||||
mediaPlayer.play();
|
||||
updateStatus("正在播放: " + project + "/" + videoName);
|
||||
|
||||
// 更新按钮状态
|
||||
playButton.setDisable(true);
|
||||
pauseButton.setDisable(false);
|
||||
stopButton.setDisable(false);
|
||||
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
showError("URL编码错误: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
showError("播放错误: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMediaListeners() {
|
||||
mediaPlayer.setOnReady(() -> {
|
||||
updateStatus("媒体已加载完成");
|
||||
progressBar.setProgress(0);
|
||||
});
|
||||
|
||||
mediaPlayer.setOnPlaying(() -> {
|
||||
updateStatus("播放中...");
|
||||
});
|
||||
|
||||
mediaPlayer.setOnPaused(() -> {
|
||||
updateStatus("已暂停");
|
||||
});
|
||||
|
||||
mediaPlayer.setOnStopped(() -> {
|
||||
updateStatus("已停止");
|
||||
resetControls();
|
||||
});
|
||||
|
||||
mediaPlayer.setOnEndOfMedia(() -> {
|
||||
updateStatus("播放完成");
|
||||
resetControls();
|
||||
progressBar.setProgress(1.0);
|
||||
});
|
||||
|
||||
mediaPlayer.setOnError(() -> {
|
||||
String errorMessage = mediaPlayer.getError() != null ?
|
||||
mediaPlayer.getError().getMessage() : "未知错误";
|
||||
showError("媒体错误: " + errorMessage);
|
||||
resetControls();
|
||||
});
|
||||
|
||||
// 更新进度条
|
||||
mediaPlayer.currentTimeProperty().addListener((obs, oldTime, newTime) -> {
|
||||
if (mediaPlayer.getTotalDuration().greaterThan(Duration.ZERO)) {
|
||||
double progress = newTime.toMillis() / mediaPlayer.getTotalDuration().toMillis();
|
||||
progressBar.setProgress(progress);
|
||||
seekSlider.setValue(progress * 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void pauseVideo() {
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.pause();
|
||||
pauseButton.setDisable(true);
|
||||
playButton.setDisable(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopVideo() {
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.stop();
|
||||
resetControls();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetControls() {
|
||||
playButton.setDisable(false);
|
||||
pauseButton.setDisable(true);
|
||||
stopButton.setDisable(true);
|
||||
progressBar.setProgress(0);
|
||||
seekSlider.setValue(0);
|
||||
}
|
||||
|
||||
private void updateStatus(String message) {
|
||||
Platform.runLater(() -> {
|
||||
statusLabel.setText(message);
|
||||
statusLabel.setStyle("-fx-text-fill: #2E8B57; -fx-font-weight: bold;");
|
||||
});
|
||||
}
|
||||
|
||||
private void showError(String message) {
|
||||
Platform.runLater(() -> {
|
||||
statusLabel.setText("错误: " + message);
|
||||
statusLabel.setStyle("-fx-text-fill: #FF4500; -fx-font-weight: bold;");
|
||||
});
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
}
|
||||
171
旧的java项目/src/main/java/com/example/sjkbf/util/JwtTokenUtil.java
Normal file
171
旧的java项目/src/main/java/com/example/sjkbf/util/JwtTokenUtil.java
Normal file
@@ -0,0 +1,171 @@
|
||||
package com.example.sjkbf.util;
|
||||
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* JWT 工具类
|
||||
* - 负责 Token 的生成、解析、验证
|
||||
* - 采用 HMAC-SHA 算法进行签名,保证安全性
|
||||
* - 适配 JJWT 0.11.x 版本
|
||||
*/
|
||||
@Component
|
||||
public class JwtTokenUtil {
|
||||
|
||||
// 从配置文件中注入 JWT 密钥和过期时间
|
||||
@Value("${jwt.secret}")
|
||||
private String secret; // 密钥(至少 32 位,推荐 64 位随机字符串)
|
||||
|
||||
@Value("${jwt.expiration}")
|
||||
private Long expiration; // Token 有效期(秒)
|
||||
|
||||
/**
|
||||
* 生成安全的 HMAC-SHA 密钥
|
||||
* - 避免直接使用原始字符串,提升安全性
|
||||
*/
|
||||
private SecretKey generateSecretKey() {
|
||||
return Keys.hmacShaKeyFor(secret.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 Token
|
||||
* @param userDetails 用户信息(包含用户名、权限等)
|
||||
* @return Token 字符串
|
||||
*/
|
||||
public String generateToken(UserDetails userDetails) {
|
||||
// 1. 定义 Token 的 Claims(载荷)
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("username", userDetails.getUsername());
|
||||
// 将权限列表转换为字符串(例如 "ROLE_ADMIN,ROLE_USER")
|
||||
claims.put("authorities", userDetails.getAuthorities().stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
// 2. 生成 Token
|
||||
return Jwts.builder()
|
||||
.setClaims(claims) // 自定义载荷
|
||||
.setSubject(userDetails.getUsername()) // 主题(通常放用户名)
|
||||
.setIssuedAt(new Date()) // 签发时间
|
||||
.setExpiration(new Date(System.currentTimeMillis() + expiration * 1000)) // 过期时间
|
||||
.signWith(generateSecretKey()) // 签名算法和密钥
|
||||
.compact(); // 生成字符串
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Token 中解析用户名
|
||||
* @param token JWT Token
|
||||
* @return 用户名
|
||||
*/
|
||||
public String getUsernameFromToken(String token) {
|
||||
return parseToken(token).getSubject();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Token 中解析权限列表
|
||||
* @param token JWT Token
|
||||
* @return 权限列表(例如 ["ROLE_ADMIN", "ROLE_USER"])
|
||||
*/
|
||||
public List<String> getAuthoritiesFromToken(String token) {
|
||||
Claims claims = parseToken(token);
|
||||
return claims.get("authorities", List.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 Token 是否有效(基础验证)
|
||||
* - 检查签名是否正确
|
||||
* - 检查是否过期
|
||||
* @param token JWT Token
|
||||
* @return 是否有效
|
||||
*/
|
||||
public boolean validateToken(String token) {
|
||||
|
||||
Claims claims = parseToken(token);
|
||||
// 检查是否过期(parseToken 内部已自动验证过期时间)
|
||||
return !claims.getExpiration().before(new Date());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证 Token 是否属于指定用户(业务层扩展验证)
|
||||
* @param token JWT Token
|
||||
* @param userDetails 用户信息
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public boolean validateTokenBelongsToUser(String token, UserDetails userDetails) {
|
||||
String username = getUsernameFromToken(token);
|
||||
return username.equals(userDetails.getUsername());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 Token(内部方法)
|
||||
* @param token JWT Token
|
||||
* @return 解析后的 Claims 对象
|
||||
* @throws JwtException 解析失败时抛出异常(如签名错误、格式错误)
|
||||
*/
|
||||
public Claims parseToken(String token) {
|
||||
try {
|
||||
return Jwts.parserBuilder()
|
||||
.setSigningKey(generateSecretKey())
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
} catch (JwtException e) {
|
||||
throw new JwtException("Token 已过期");
|
||||
}
|
||||
}
|
||||
// ---------- 扩展方法:自定义 Claims ----------
|
||||
|
||||
/**
|
||||
* 添加自定义 Claim(在生成 Token 前调用)
|
||||
* 示例:添加用户ID
|
||||
* Map<String, Object> claims = new HashMap<>();
|
||||
* claims.put("userId", 123);
|
||||
* String token = jwtTokenUtil.generateToken(userDetails, claims);
|
||||
*/
|
||||
public String generateToken(UserDetails userDetails, Map<String, Object> customClaims) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.putAll(customClaims); // 合并自定义 Claims
|
||||
claims.put("authorities", userDetails.getAuthorities().stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
return Jwts.builder()
|
||||
.setClaims(claims)
|
||||
.setSubject(userDetails.getUsername())
|
||||
.setIssuedAt(new Date())
|
||||
.setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
|
||||
.signWith(generateSecretKey())
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取自定义 Claim
|
||||
* 示例:Long userId = jwtTokenUtil.getClaimFromToken(token, "userId", Long.class);
|
||||
*/
|
||||
public <T> T getClaimFromToken(String token, String claimName, Class<T> clazz) {
|
||||
Claims claims = parseToken(token);
|
||||
return claims.get(claimName, clazz);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从请求中获取 Token
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public String getTokenFromRequest(HttpServletRequest request) {
|
||||
String header = request.getHeader("Authorization");
|
||||
if (header != null && header.startsWith("Bearer ")) {
|
||||
return header.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
44
旧的java项目/src/main/java/com/example/sjkbf/util/MD5.java
Normal file
44
旧的java项目/src/main/java/com/example/sjkbf/util/MD5.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package com.example.sjkbf.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class MD5 {
|
||||
// 全局数组
|
||||
private final static String[] strDigits = {"0", "1", "2", "3", "4", "5",
|
||||
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "j", "?", "~"};
|
||||
|
||||
|
||||
// 返回形式为数字跟字符串
|
||||
private static String byteToArrayString(byte bByte) {
|
||||
int iRet = bByte;
|
||||
if (iRet < 0) {
|
||||
iRet += 256;
|
||||
}
|
||||
int iD1 = iRet / 16;
|
||||
int iD2 = iRet % 16;
|
||||
return strDigits[iD1] + strDigits[iD2];
|
||||
}
|
||||
|
||||
// 转换字节数组为16进制字串
|
||||
private static String byteToString(byte[] bByte) {
|
||||
StringBuffer sBuffer = new StringBuffer();
|
||||
for (int i = 0; i < bByte.length; i++) {
|
||||
sBuffer.append(byteToArrayString(bByte[i]));
|
||||
}
|
||||
return sBuffer.toString();
|
||||
}
|
||||
|
||||
public static String getMD5Code(String strObj) {
|
||||
String resultString = null;
|
||||
try {
|
||||
// resultString = new String(strObj);
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
// md.digest() 该函数返回值为存放哈希值结果的byte数组
|
||||
resultString = byteToString(md.digest(strObj.getBytes("UTF-8")));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return resultString;
|
||||
}
|
||||
|
||||
}
|
||||
223
旧的java项目/src/main/java/com/example/sjkbf/util/RSATooL.java
Normal file
223
旧的java项目/src/main/java/com/example/sjkbf/util/RSATooL.java
Normal file
@@ -0,0 +1,223 @@
|
||||
package com.example.sjkbf.util;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.asymmetric.RSA;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class RSATooL {
|
||||
|
||||
|
||||
private static String prkey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANp/KnuAZq609lnc\n" +
|
||||
"jciVgt/xDLDEaKC+DSuSZc9o/fgLqweL/8Yu5iPAzoBQlO1t+jSkI2YuoFsKKK7O\n" +
|
||||
"QFcSoz4Z5Lb7vOG7XJ4Re/6L2LJIU9tjJ3LznW5WKnuiqxs0ziIZilLkRE0P1di6\n" +
|
||||
"FIZQUjmn2KQ2y/P7PuviJPat3y+vAgMBAAECgYEAmn64h0MvV/FVEA1Ho8E0HSzQ\n" +
|
||||
"kF0Qrjg0D88gdhwDGFUHxfpUDMo0qKs4WLqh05CkDnzRGvt1H2p7gb8M94SSL5SX\n" +
|
||||
"mCR2ZLiCQJy5tZpQNRUt9P67upLcDcKJ6YPujcuEdlo0pzKGGMZk8Uvh05S9lnwl\n" +
|
||||
"yWJeEk4G7q5Aalz8vIECQQDwBVJH60Gd2St/GS4dCtXwHTO9HJZRaWEkaXPgVbXI\n" +
|
||||
"vqv+jtD4HpzDCpgv/kUK0fnb4V/9/LM1SHOedVMfmh0fAkEA6QsChdHiU1lHfL1b\n" +
|
||||
"Z3Uvxvi/Zk8i0ryzBaYudrzNmb7iJcssJPPty3KTjihgvw2W36GV+2GlQBEjOf2B\n" +
|
||||
"2WgLcQJBAO66XDxsIbd+aWThBpycSm2one1aoagXyCcPO9HFbilcfHWUVwRybjkQ\n" +
|
||||
"MI6LuOAqOPoaD//vd89nYJga2bJ09sECQFmXRPoDTVozqXr4JSqp75szyAliBQY1\n" +
|
||||
"SzGxyI0XWodvzesvp6HxMQsU2ks9lKv+YnFI4qsIyAnQTNWfcwsMp9ECQDba0LJV\n" +
|
||||
"xI0SIznsVtBb7T5Ir9ppLKx1QTNcytkjHxmQqWGy+57ojjQ6GV3z4fSwNGjIhsOT\n" +
|
||||
"DFgz0gEcRr13bRk=";
|
||||
private static String pubkey =
|
||||
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDafyp7gGautPZZ3I3IlYLf8Qyw\n" +
|
||||
"xGigvg0rkmXPaP34C6sHi//GLuYjwM6AUJTtbfo0pCNmLqBbCiiuzkBXEqM+GeS2\n" +
|
||||
"+7zhu1yeEXv+i9iySFPbYydy851uVip7oqsbNM4iGYpS5ERND9XYuhSGUFI5p9ik\n" +
|
||||
"Nsvz+z7r4iT2rd8vrwIDAQAB";
|
||||
static RSA rsa2 = new RSA(prkey, pubkey);
|
||||
|
||||
/**
|
||||
* 解密
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String decrypt(String str){
|
||||
|
||||
str= str.replaceAll(" ","+");
|
||||
byte[] decrypt2 = rsa2.decrypt(str, KeyType.PrivateKey);
|
||||
String s = new String(decrypt2);
|
||||
String[] split = s.split("");
|
||||
s = split[0];
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String encryption(String str){
|
||||
return Base64.encode(rsa2.encrypt(str, KeyType.PrivateKey));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 使用RSA公钥解密
|
||||
* @param encryptedData 加密后的数据(Base64编码)
|
||||
* @return 解密后的原始字符串
|
||||
*/
|
||||
public static String decryptByPublicKey( String encryptedData) {
|
||||
|
||||
|
||||
// 解密步骤:
|
||||
// 1. 将Base64编码的加密数据解码为字节数组
|
||||
// 2. 使用公钥解密(指定KeyType.PublicKey)
|
||||
// 3. 将解密后的字节数组转换为字符串
|
||||
byte[] decryptedBytes = rsa2.decrypt(Base64.decode(encryptedData), KeyType.PublicKey);
|
||||
|
||||
return new String(decryptedBytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(decompress("H4sIAAAAAAAAAKtWyk6tVLJSUggKdgzJz/fRS81LLqosKMnMz9MAyhTrleQHlxRl5qVraCrVAgAXNYHCLQAAAA=="));
|
||||
}
|
||||
|
||||
//异或加密
|
||||
public static byte[] Makecode(byte[] pstr,int[] Key) {
|
||||
byte[] Str = pstr;
|
||||
|
||||
for (int i = 0; i < Str.length; i++) {
|
||||
byte sbuf = Str[i];
|
||||
Str[i] = MakecodeChar(sbuf, Key[i % 20], Key[(i + 18) % 20]);
|
||||
}
|
||||
|
||||
return Str;
|
||||
}
|
||||
|
||||
//字符串异或
|
||||
public static String encryptDecrypt(String input, String key) {
|
||||
StringBuilder output = new StringBuilder(input);
|
||||
int keyLength = key.length();
|
||||
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
// 对每个字符进行异或运算
|
||||
output.setCharAt(i, (char) (input.charAt(i) ^ key.charAt(i % keyLength)));
|
||||
}
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
|
||||
//单个字符加密
|
||||
public static byte MakecodeChar(byte c, int key, int key2) {
|
||||
return (byte) ((((c + key) ^ key2) ^ key) + 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 单个字符解密,对应C++的CutcodeChar
|
||||
* @param c 待解密的字符(Java中用byte表示,对应C++的char)
|
||||
* @param key 第一个密钥
|
||||
* @param key2 第二个密钥
|
||||
* @return 解密后的字符(byte)
|
||||
*/
|
||||
public static byte cutcodeChar(byte c, int key, int key2) {
|
||||
// 对应C++的:(((c - 1) ^ key) ^ key2) - key
|
||||
// 注意:Java中byte是8位有符号数,运算时会自动提升为int,最后强转为byte
|
||||
int step1 = (c - 1) ^ key;
|
||||
int step2 = step1 ^ key2;
|
||||
int result = step2 - key;
|
||||
return (byte) result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字节数组解密,对应C++的Cutecode
|
||||
* @param pstr 待解密的字节数组(对应C++的char*)
|
||||
* @param pkey 密钥数组
|
||||
* @param len 待解密的长度(-1表示使用整个数组长度)
|
||||
* @param keyLength 密钥长度(默认5,与C++默认参数一致)
|
||||
* @return 解密后的字节数组(原数组会被修改,同时返回新数组方便链式调用)
|
||||
*/
|
||||
public static byte[] cutecode(byte[] pstr, int[] pkey, int len, int keyLength) {
|
||||
// 处理默认长度:如果len为-1,则使用数组的实际长度
|
||||
if (len == -1) {
|
||||
len = pstr.length;
|
||||
}
|
||||
// 遍历每个字节进行解密
|
||||
for (int i = 0; i < len; i++) {
|
||||
// 计算密钥索引,与C++逻辑一致
|
||||
int keyIndex = i % keyLength;
|
||||
int key2Index = (i + 18) % keyLength;
|
||||
// 调用单个字符解密方法,修改原数组
|
||||
pstr[i] = cutcodeChar(pstr[i], pkey[keyIndex], pkey[key2Index]);
|
||||
}
|
||||
return pstr;
|
||||
}
|
||||
|
||||
// 重载方法:提供默认参数(对应C++的默认参数int keyLength = 5)
|
||||
public static byte[] cutecode(byte[] pstr, int[] pkey, int len) {
|
||||
return cutecode(pstr, pkey, len, 5);
|
||||
}
|
||||
|
||||
// 重载方法:最简化调用(len=-1,keyLength=5)
|
||||
public static byte[] cutecode(byte[] pstr, int[] pkey) {
|
||||
return cutecode(pstr, pkey, -1, 5);
|
||||
}
|
||||
/**
|
||||
* 压缩字符串
|
||||
* @param input 原始字符串
|
||||
* @return Base64编码后的压缩字符串(便于存储/传输)
|
||||
*/
|
||||
public static String compress(String input) {
|
||||
if (input == null || input.isEmpty()) {
|
||||
return input;
|
||||
}
|
||||
|
||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzipOS = new GZIPOutputStream(bos)) {
|
||||
|
||||
gzipOS.write(input.getBytes(StandardCharsets.UTF_8));
|
||||
gzipOS.finish();
|
||||
|
||||
// 将压缩后的字节数组转为Base64字符串(避免二进制乱码)
|
||||
byte[] compressedBytes = bos.toByteArray();
|
||||
return java.util.Base64.getEncoder().encodeToString(compressedBytes);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("压缩失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解压字符串
|
||||
* @param compressedStr Base64编码后的压缩字符串
|
||||
* @return 解压后的原始字符串
|
||||
*/
|
||||
public static String decompress(String compressedStr) {
|
||||
if (compressedStr == null || compressedStr.isEmpty()) {
|
||||
return compressedStr;
|
||||
}
|
||||
|
||||
byte[] compressedBytes = java.util.Base64.getDecoder().decode(compressedStr);
|
||||
System.out.println(Arrays.toString(compressedBytes));
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(compressedBytes);
|
||||
GZIPInputStream gzipIS = new GZIPInputStream(bis);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = gzipIS.read(buffer)) != -1) {
|
||||
bos.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
return new String(bos.toByteArray(), StandardCharsets.UTF_8);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("解压失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
package com.example.sjkbf.util;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.symmetric.AES;
|
||||
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.*;
|
||||
|
||||
public class SimpleNutZipCompatible {
|
||||
|
||||
// 字节级别的加密解密
|
||||
public static byte[] encryptDecryptBytes(byte[] data, String key) {
|
||||
byte[] result = new byte[data.length];
|
||||
byte[] keyBytes = key.getBytes();
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
result[i] = (byte) (data[i] ^ keyBytes[i % keyBytes.length]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String operation = "encrypt"; // 或 "decrypt"
|
||||
String sourcePath = "C:\\Users\\12134\\Desktop\\fsdownload\\DPS_Script";
|
||||
String targetPath = "C:\\Users\\12134\\Desktop\\fsdownload\\DPS_Script\\sut.tar.gz";
|
||||
String key = "Rindro-Aurora";
|
||||
|
||||
if ("encrypt".equals(operation)) {
|
||||
// 加密并压缩
|
||||
encryptAndZip(sourcePath, targetPath, key);
|
||||
} else {
|
||||
// 解压并解密
|
||||
decryptFromZip(sourcePath, targetPath, key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 检查文件是否在_Core子目录下
|
||||
*/
|
||||
private static boolean isInRootOrCore(Path filePath, Path sourcePath) {
|
||||
Path relativePath = sourcePath.relativize(filePath);
|
||||
int nameCount = relativePath.getNameCount();
|
||||
|
||||
// _Core子目录下的文件(相对路径的第一个目录是_Core)
|
||||
if (nameCount >= 2 && "_Core".equals(relativePath.getName(0).toString())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static void encryptAndZip(String folderPath, String zipPath, String key) {
|
||||
|
||||
// 随机生成密钥
|
||||
byte[] keyBytes = {92, -2, -65, 10, 118, 103, -68, 72, -23, 124, -103, -39, 0, -128, 31, -107};
|
||||
|
||||
|
||||
System.out.println("密钥: " + Arrays.toString(keyBytes));
|
||||
|
||||
// 构建
|
||||
AES aes = SecureUtil.aes(keyBytes);
|
||||
|
||||
|
||||
Path tempDir = null;
|
||||
try {
|
||||
// 创建临时目录
|
||||
tempDir = Files.createTempDirectory("nut_encrypt");
|
||||
Path sourcePath = Paths.get(folderPath);
|
||||
|
||||
// 加密所有.nut文件到临时目录
|
||||
Path finalTempDir = tempDir;
|
||||
Files.walk(sourcePath)
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(path -> (path.toString().toLowerCase().endsWith(".nut")))
|
||||
.filter(path -> isInRootOrCore(path, sourcePath))
|
||||
.forEach(nutFile -> {
|
||||
try {
|
||||
byte[] content = Files.readAllBytes(nutFile);
|
||||
byte[] encrypted = aes.encrypt(content);
|
||||
|
||||
Path relative = sourcePath.relativize(nutFile);
|
||||
Path tempFile = finalTempDir.resolve(relative);
|
||||
|
||||
String newName = tempFile.getFileName().toString().replace(".nut", ".nut");
|
||||
Path sutFile = tempFile.getParent().resolve(newName);
|
||||
|
||||
Files.createDirectories(sutFile.getParent());
|
||||
Files.write(sutFile, encrypted);
|
||||
|
||||
System.out.println("加密: " + relative);
|
||||
} catch (Exception e) {
|
||||
System.err.println("错误: " + nutFile + " - " + e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
FileReader fileReader = new FileReader(folderPath + "/FileConfig.json");
|
||||
String result5 = fileReader.readString();
|
||||
//转json
|
||||
JSONObject jsonObject = new JSONObject(result5);
|
||||
|
||||
jsonObject.remove("ProjectScript");
|
||||
|
||||
|
||||
String string = tempDir.toAbsolutePath()+"/FileConfig.json";
|
||||
FileUtil.writeString(jsonObject.toString(),string, "utf-8");
|
||||
|
||||
|
||||
|
||||
// 压缩临时目录
|
||||
zipFolderToTarGz(tempDir.toString(), zipPath);
|
||||
System.out.println("压缩完成: " + zipPath);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("加密压缩失败: " + e.getMessage());
|
||||
} finally {
|
||||
if (tempDir != null) {
|
||||
deleteDirectory(tempDir.toFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void decryptFromZip(String zipPath, String outputFolder, String key) {
|
||||
try {
|
||||
Path outputPath = Paths.get(outputFolder);
|
||||
Files.createDirectories(outputPath);
|
||||
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipPath))) {
|
||||
ZipEntry entry;
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
if (!entry.isDirectory() && entry.getName().toLowerCase().endsWith(".sut")) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
baos.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
byte[] encrypted = baos.toByteArray();
|
||||
byte[] decrypted = encryptDecryptBytes(encrypted, key);
|
||||
|
||||
Path outputFile = outputPath.resolve(entry.getName());
|
||||
String newName = outputFile.getFileName().toString().replace(".sut", ".nut");
|
||||
Path nutFile = outputFile.getParent().resolve(newName);
|
||||
|
||||
Files.createDirectories(nutFile.getParent());
|
||||
Files.write(nutFile, decrypted);
|
||||
|
||||
System.out.println("解密: " + entry.getName());
|
||||
}
|
||||
zis.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("解密完成: " + outputFolder);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("解压解密失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void zipFolder(String srcFolder, String zipPath) {
|
||||
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipPath))) {
|
||||
File folder = new File(srcFolder);
|
||||
zipDirectory(folder, zos, "");
|
||||
} catch (IOException e) {
|
||||
System.err.println("压缩错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void zipDirectory(File folder, ZipOutputStream zos, String parentPath) throws IOException {
|
||||
for (File file : folder.listFiles()) {
|
||||
if (file.isDirectory()) {
|
||||
zipDirectory(file, zos, parentPath + file.getName() + "/");
|
||||
} else {
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
zos.putNextEntry(new ZipEntry(parentPath + file.getName()));
|
||||
byte[] buffer = new byte[1024];
|
||||
int length;
|
||||
while ((length = fis.read(buffer)) > 0) {
|
||||
zos.write(buffer, 0, length);
|
||||
}
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将文件夹压缩为 tar.gz 格式
|
||||
*/
|
||||
private static void zipFolderToTarGz(String sourceFolder, String tarGzPath) throws IOException {
|
||||
Path sourcePath = Paths.get(sourceFolder);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(tarGzPath);
|
||||
BufferedOutputStream bos = new BufferedOutputStream(fos);
|
||||
GZIPOutputStream gos = new GZIPOutputStream(bos);
|
||||
TarArchiveOutputStream tos = new TarArchiveOutputStream(gos)) {
|
||||
|
||||
// 设置tar格式
|
||||
tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
|
||||
|
||||
Files.walk(sourcePath)
|
||||
.filter(Files::isRegularFile)
|
||||
.forEach(file -> {
|
||||
try {
|
||||
// 获取相对路径
|
||||
Path relativePath = sourcePath.relativize(file);
|
||||
|
||||
// 创建tar条目
|
||||
TarArchiveEntry entry = new TarArchiveEntry(file.toFile(), relativePath.toString().replace("\\", "/"));
|
||||
tos.putArchiveEntry(entry);
|
||||
|
||||
// 写入文件内容
|
||||
Files.copy(file, tos);
|
||||
|
||||
tos.closeArchiveEntry();
|
||||
// System.out.println("添加到tar.gz: " + relativePath);
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("添加文件到tar.gz失败: " + file + " - " + e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
tos.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteDirectory(File dir) {
|
||||
if (dir.isDirectory()) {
|
||||
for (File file : dir.listFiles()) {
|
||||
deleteDirectory(file);
|
||||
}
|
||||
}
|
||||
dir.delete();
|
||||
}
|
||||
}
|
||||
118
旧的java项目/src/main/java/com/example/sjkbf/util/tool.java
Normal file
118
旧的java项目/src/main/java/com/example/sjkbf/util/tool.java
Normal file
@@ -0,0 +1,118 @@
|
||||
package com.example.sjkbf.util;
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.crypto.asymmetric.KeyType;
|
||||
import cn.hutool.crypto.asymmetric.RSA;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class tool {
|
||||
|
||||
|
||||
public static String encryptDecrypt(String input, String key) {
|
||||
char[] output = new char[input.length()];
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
output[i] = (char) (input.charAt(i) ^ key.charAt(i % key.length())); // 使用异或运算进行加密
|
||||
}
|
||||
return new String(output);
|
||||
}
|
||||
|
||||
|
||||
private static final String prkey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMiYuNW4K1rST7ZW" +
|
||||
"YpWX6nEziXi5JveLPhDCLj0VZ/5/4dzBWrmoL/IcFZuHOBJtYHm965713kKC9gtw" +
|
||||
"2EyVgkqmXLT3105jEUqzNizfThc6C2ZL6vMmzUZlooxNyaOC5mWthPZtwlqQihYW" +
|
||||
"T2nW/wKp8fpTouXihQOCPjqdRoVFAgMBAAECgYEAg+1dcsHjUaIL5uG9iKEXAUhh" +
|
||||
"21H6PMgJE8CB5I6VjJ3Sj/tijcP9dH/f/h/aUtQ4pRixRCRz/s5ev3uB5ixWOVOz" +
|
||||
"Uhga/NwjURlkg1Katg/14tvd8iZsAzI7KyXGdUefC8+Rulc8SBx+BqYIZ1FTLJkg" +
|
||||
"obisps6esaaNZekvS0ECQQDxPnfWuNfwfpYFK038AhEFqBiOBMsMrB/QX+O0sQ/Z" +
|
||||
"31gWkNuu3Z+cz6PG0FEK0O8/jsXQ1/gVAreADptJAMzpAkEA1N3GFV1LuYYqkp3a" +
|
||||
"y4DnmdI/LgrBUAjWSvTSDKfB8Ik2Y8I2zDS20EsEQMvQYtLxMOMHIEqeAVzmnZcS" +
|
||||
"dH4L/QJAQM/elFJuuU7Y8SSUO/s2JYXmqukAwDPSDEJmw5m6P3dwjAd47b7e7dsf" +
|
||||
"Df/Tdgtx62ppHNWY8dQcBoxmDbPoWQJBANBQBBROS9fQA4Od9Usn5/5xcSDWp51y" +
|
||||
"OHv8ID8AQNvq+44ets+aWrl2YEAk9NZxRlWoJwYj34LH7muUNxxHaeUCQQCjtLPU" +
|
||||
"din4XjlMMRSTW/EOgX4JgZ+tQaAtB32wQocPDDeHqkDusUdlEpnDPbmkE9Sbxf1p" +
|
||||
"0mSxXgnIuT99niBd";
|
||||
private static final String prkey2 = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIdcnQN/YkABlIDJ" +
|
||||
"b2wqZgYEHRJReHvIWbeyNV7zJsMZdZRmQYKi2WMmNMH3DKyW7CCzdYrvHbQ5QyqP" +
|
||||
"YaQ1X9hVv4bPzXPKSCBVPh5Cr13WwKgh3lhLmbkA/hJ9giRIo9jT47fHE3RaJkic" +
|
||||
"RyCqWDSiOsnF7gNYJQf8MAarl/oTAgMBAAECgYAvZKvM57LcujDmjqCmfInQHWyY" +
|
||||
"V1IZ9OIEwS6Smgu+T5GtbcgOFzqJzny2VOtpGkZ+hJbpGCOMUGhF5IHJXq65qvei" +
|
||||
"ejBeJEH9xnTuJcXUKtHJjIGJQsKzuNKuTddFlY9an/BzoZq4/2Txyh2z6ZDZU1z0" +
|
||||
"9pVY8tJe2FVyMY2oIQJBAKhLDMV+kfWLzDfiXijJ28DHdKCozaaAtLZRTRL/XlQU" +
|
||||
"O8phcZ0wEKkzrNvn0Fn+5VIQFu1ghWvCo4iaS181FqkCQQDN5/+nbbzZ2AqQsBDB" +
|
||||
"eCbLiXPJM7Ey69O4leMyzKL1dyI7nMl5/SeOQE/xBViqzF6M/VUGFzE1YOxl+HZA" +
|
||||
"AQxbAkA3GNsFjXqbuTkS0rmhAPVBGAvGzX0GlfyT8+oX3iMzw6wPhfd8TtAllRVy" +
|
||||
"qWI9FIZfZ4UaEg+cSAziHCGw+eCBAkAlLJWDbNSDn/WIWcEsrLyUUqSM1sBPKTR4" +
|
||||
"RtdV/IwPNQsBKDVXyNSzYfkM0qJHc84+Nh57kwRXVsBXSJxQwd+xAkB9ZzCD0sp6" +
|
||||
"8ISzFmbwL+uVtUbe/W0pLC9PDN9B7Vcw6Jf8V0B3lxB493rxTzG3o5oapDDxFIv/" +
|
||||
"I6SViudhGXfP";
|
||||
|
||||
private static final String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHXJ0Df2JAAZSAyW9sKmYGBB0S" +
|
||||
"UXh7yFm3sjVe8ybDGXWUZkGCotljJjTB9wysluwgs3WK7x20OUMqj2GkNV/YVb+G" +
|
||||
"z81zykggVT4eQq9d1sCoId5YS5m5AP4SfYIkSKPY0+O3xxN0WiZInEcgqlg0ojrJ" +
|
||||
"xe4DWCUH/DAGq5f6EwIDAQAB";
|
||||
|
||||
|
||||
|
||||
static RSA rsa2 = new RSA(prkey, null);
|
||||
static RSA rsa22 = new RSA(prkey2, publicKey);
|
||||
|
||||
public static String getIpAddress(HttpServletRequest request) {
|
||||
// 获取请求的IP地址
|
||||
String ipAddress = request.getRemoteAddr();
|
||||
// 如果应用部署在反向代理或负载均衡器后面,可以通过X-Forwarded-For头部获取真实IP地址
|
||||
String forwardedFor = request.getHeader("X-Forwarded-For");
|
||||
if (forwardedFor != null && !forwardedFor.isEmpty()) {
|
||||
ipAddress = forwardedFor.split(",")[0];
|
||||
}
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解密
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String decrypt(String str){
|
||||
|
||||
str= str.replaceAll(" ","+");
|
||||
byte[] decrypt2 = rsa2.decrypt(str, KeyType.PublicKey);
|
||||
String s = new String(decrypt2);
|
||||
String[] split = s.split("");
|
||||
s = split[0];
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String encryption(String str){
|
||||
return Base64.encode(rsa2.encrypt(str, KeyType.PrivateKey));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加密2
|
||||
* @param str
|
||||
* @return
|
||||
*/
|
||||
public static String encryption2(String str){
|
||||
return Base64.encode(rsa22.encrypt(str, KeyType.PrivateKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密
|
||||
*/
|
||||
public static String decrypt2(String str){
|
||||
//先进行base64解密
|
||||
str= Base64.decodeStr(str);
|
||||
byte[] decrypt2 = rsa22.decrypt(str, KeyType.PublicKey);
|
||||
String s = new String(decrypt2);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
0
旧的java项目/src/main/resources/application.properties
Normal file
0
旧的java项目/src/main/resources/application.properties
Normal file
78
旧的java项目/src/main/resources/application.yml
Normal file
78
旧的java项目/src/main/resources/application.yml
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
server:
|
||||
port: 8651
|
||||
# ssl:
|
||||
# key-store: classpath:yosin.jks
|
||||
# key-store-type: JKS
|
||||
# key-password: 2luolita
|
||||
|
||||
|
||||
|
||||
#spring:
|
||||
# datasource:
|
||||
# dynamic:
|
||||
# primary: master #??????????????,?????master
|
||||
# strict: false #???????,??false. true?????????????,false???????
|
||||
# datasource:
|
||||
# master:
|
||||
# url: jdbc:mysql://127.0.0.1:3306/taiwan_cain_2nd?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
|
||||
# username: game
|
||||
# password: uu5!^%jg
|
||||
# driver-class-name: com.mysql.jdbc.Driver # 3.2.0????SPI??????
|
||||
|
||||
|
||||
jwt:
|
||||
secret: "rjyusrghdfghj2345ryu123asdfvbyukuirtwjhfsd" # 至少 32 位
|
||||
expiration: 7200 # 2 小时(单位:秒)
|
||||
#
|
||||
#
|
||||
#
|
||||
#spring:
|
||||
# # 配置数据源信息
|
||||
# datasource:
|
||||
# dynamic:
|
||||
# # 设置默认的数据源或者数据源组,默认值即为master
|
||||
# primary: master
|
||||
# # 严格匹配数据源,默认false.true未匹配到指定数据源时抛异常,false使用默认数据源
|
||||
# strict: false
|
||||
# datasource:
|
||||
# master:
|
||||
# url: jdbc:mysql://192.168.200.25:3306/rindro?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root2
|
||||
# password: 527700
|
||||
# driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0????SPI??????
|
||||
#pro:
|
||||
# configfile: "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\Script\\FileConfig.json"
|
||||
# userfile: "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\"
|
||||
# filemap: "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\file.json"
|
||||
# scriptfile: "C:\\Users\\12134\\Desktop\\工作目录\\rindro\\ClentScript\\"
|
||||
# dps: "C:\\Users\\12134\\Desktop\\工作目录\\home\\DP_S\\"
|
||||
|
||||
#
|
||||
spring:
|
||||
# 配置数据源信息
|
||||
datasource:
|
||||
dynamic:
|
||||
# 设置默认的数据源或者数据源组,默认值即为master
|
||||
primary: master
|
||||
# 严格匹配数据源,默认false.true未匹配到指定数据源时抛异常,false使用默认数据源
|
||||
strict: false
|
||||
datasource:
|
||||
master:
|
||||
# url: jdbc:mysql://110.40.74.134:3306/rindro?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
# username: root
|
||||
# password: 527700
|
||||
url: jdbc:mysql://110.42.251.214:3306/rindro?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: Yosin0102!
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0????SPI??????
|
||||
pro:
|
||||
configfile: "/root/rindro/Script/FileConfig.json"
|
||||
userfile: "/root/rindro/"
|
||||
filemap: "/root/rindro/file.json"
|
||||
scriptfile: "/root/rindro/ClentScript/"
|
||||
dps: "/home/DP_S/"
|
||||
|
||||
#mybatis-plus:
|
||||
# configuration:
|
||||
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 直接在控制台打印SQL
|
||||
5
旧的java项目/src/main/resources/mapper/LogMapper.xml
Normal file
5
旧的java项目/src/main/resources/mapper/LogMapper.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?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.sjkbf.mapper.LogMapper">
|
||||
|
||||
</mapper>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user