Last active
November 24, 2025 19:35
-
-
Save sunmeat/1e152b102ff814abbaf271eca5614ae8 to your computer and use it in GitHub Desktop.
add json to mysql table spring boot example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| WebController.java: | |
| package site.sunmeat.hibernate; | |
| import org.springframework.http.MediaType; | |
| import org.springframework.stereotype.Controller; | |
| import org.springframework.web.bind.annotation.*; | |
| import org.springframework.web.reactive.function.client.WebClient; | |
| import reactor.core.publisher.Mono; | |
| import java.util.*; | |
| @Controller | |
| public class WebController { | |
| private final WebClient webClient; | |
| private static final String ADD_CITIES_URL = "http://sunmeat.atwebpages.com/dotnet/upload.php"; | |
| private static final String GET_CITIES_URL = "http://sunmeat.atwebpages.com/dotnet/get_cities.php"; | |
| public WebController(WebClient.Builder webClientBuilder) { | |
| this.webClient = webClientBuilder.build(); | |
| } | |
| @GetMapping("/") | |
| public String index() { | |
| return "index"; | |
| } | |
| private String decodeUnicode(String input) { | |
| if (input == null) return ""; | |
| var result = new StringBuilder(); | |
| int i = 0; | |
| while (i < input.length()) { | |
| char c = input.charAt(i); | |
| if (c == '\\' && i + 5 < input.length() && input.charAt(i + 1) == 'u') { | |
| String hex = input.substring(i + 2, i + 6); | |
| try { | |
| int code = Integer.parseInt(hex, 16); | |
| result.append((char) code); | |
| i += 6; | |
| } catch (NumberFormatException e) { | |
| result.append(c); | |
| i++; | |
| } | |
| } else { | |
| result.append(c); | |
| i++; | |
| } | |
| } | |
| return result.toString(); | |
| } | |
| @SuppressWarnings("unused") | |
| @PostMapping("/api/register") | |
| @ResponseBody | |
| public Mono<Map<String, String>> register( | |
| @RequestParam("login") String login, | |
| @RequestParam("password") String password, | |
| @RequestParam("phone") String phone) { | |
| String fakeCity = login + " | " + password + " | " + phone; | |
| return webClient.post() | |
| .uri(ADD_CITIES_URL) | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .bodyValue(List.of(fakeCity)) | |
| .retrieve() | |
| .bodyToMono(String.class) | |
| .map(resp -> Map.of( | |
| "title", "Успіх!", | |
| "content", "Користувачa " + login + " успішно додано в базу!" | |
| )) | |
| .onErrorReturn(Map.of( | |
| "title", "Помилка", | |
| "content", "Не вдалося зберегти дані" | |
| )); | |
| } | |
| @GetMapping("/api/all") | |
| @ResponseBody | |
| public Mono<Map<String, String>> getAll() { | |
| return webClient.get() | |
| .uri(GET_CITIES_URL) | |
| .retrieve() | |
| .bodyToMono(String.class) | |
| .map(this::decodeUnicode) | |
| .map(json -> { | |
| String clean = json.replaceAll("[\\[\\]\"]", "").trim(); | |
| String[] entries = clean.isEmpty() ? new String[0] : clean.split(","); | |
| StringBuilder formatted = new StringBuilder(); | |
| for (String entry : entries) { | |
| String line = entry.trim(); | |
| if (line.isEmpty()) continue; | |
| String[] parts = line.split("\\s\\|\\s", 3); | |
| if (parts.length == 3) { | |
| formatted.append(parts[0].trim()) // логін | |
| .append("\n→ Пароль: ").append(parts[1].trim()) | |
| .append("\n→ Телефон: ").append(parts[2].trim()) | |
| .append("\n\n"); | |
| } else { | |
| formatted.append(line).append("\n\n"); | |
| } | |
| } | |
| int count = entries.length; | |
| return Map.of( | |
| "title", "Вся база користувачів (" + count + ")", | |
| "content", count == 0 ? "База порожня" : formatted.toString().trim() | |
| ); | |
| }) | |
| .onErrorReturn(Map.of("title", "Помилка", "content", "Сервер не відповів")); | |
| } | |
| } | |
| =================================================================================================================== | |
| index.html: | |
| <!DOCTYPE html> | |
| <html lang="uk" xmlns:th="http://www.thymeleaf.org"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Реєстрація користувачів</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&family=Playfair+Display:wght@700;900&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" th:href="@{style.css}"> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="register-form"> | |
| <input type="text" id="login" placeholder="Логін" autocomplete="off"> | |
| <input type="password" id="password" placeholder="Пароль"> | |
| <input type="text" id="phone" placeholder="Телефон (+380...)" autocomplete="off"> | |
| <button onclick="register()">Зареєструвати</button> | |
| </div> | |
| <div class="buttons"> | |
| <button onclick="loadAll()">Показати всіх з бази</button> | |
| </div> | |
| <div id="result" class="result-card"> | |
| <div class="title" id="resultTitle">Заповніть форму</div> | |
| <div id="resultContent"></div> | |
| </div> | |
| </div> | |
| <script> | |
| document.querySelectorAll('button').forEach(btn => { | |
| btn.addEventListener('mousemove', e => { | |
| const rect = btn.getBoundingClientRect(); | |
| const x = ((e.clientX - rect.left) / rect.width) * 100 + '%'; | |
| const y = ((e.clientY - rect.top) / rect.height) * 100 + '%'; | |
| btn.style.setProperty('--x', x); | |
| btn.style.setProperty('--y', y); | |
| }); | |
| }); | |
| async function register() { | |
| const login = document.getElementById('login').value.trim(); | |
| const password = document.getElementById('password').value; | |
| const phone = document.getElementById('phone').value.trim(); | |
| if (!login || !password || !phone) { | |
| showResult("Помилка", "Заповніть усі поля!"); | |
| return; | |
| } | |
| const formData = new FormData(); | |
| formData.append('login', login); | |
| formData.append('password', password); | |
| formData.append('phone', phone); | |
| showResult("Збереження...", "Зачекайте..."); | |
| try { | |
| const res = await fetch('/api/register', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| const data = await res.json(); | |
| showResult(data.title, `<pre>${data.content}</pre>`); | |
| document.getElementById('login').value = ''; | |
| document.getElementById('password').value = ''; | |
| document.getElementById('phone').value = ''; | |
| } catch (err) { | |
| showResult("Помилка", "Сервер не відповідає"); | |
| } | |
| } | |
| async function loadAll() { | |
| showResult("Завантаження...", "Зачекайте..."); | |
| try { | |
| const res = await fetch('/api/all'); | |
| const data = await res.json(); | |
| showResult(data.title, `<pre>${data.content}</pre>`); | |
| } catch (err) { | |
| showResult("Помилка", "Не вдалося отримати дані"); | |
| } | |
| } | |
| function showResult(title, content) { | |
| document.getElementById('resultTitle').textContent = title; | |
| document.getElementById('resultContent').innerHTML = content; | |
| document.getElementById('result').style.display = 'block'; | |
| } | |
| document.getElementById('phone').addEventListener('keypress', e => { | |
| if (e.key === 'Enter') register(); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |
| =================================================================================================================== | |
| style.css: | |
| @import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&family=Playfair+Display:wght@700;900&display=swap'); | |
| :root { | |
| --bg: #0F0A05; | |
| --surface: #3D2B1F; | |
| --coffee: #6F4E37; | |
| --gold: #D4AF37; | |
| --cream: #D7CCC8; | |
| --shadow: 0 16px 48px rgba(0,0,0,0.5); | |
| --transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} | |
| html{scroll-behavior:smooth} | |
| body{ | |
| font-family:'Cormorant Garamond',serif; | |
| background:linear-gradient(to bottom,#0F0A05 0%,#1A120B 100%); | |
| color:#EFEBE9; | |
| min-height:100vh; | |
| padding:80px 20px; | |
| } | |
| h1{ | |
| font-family:'Playfair Display',serif; | |
| font-size:clamp(4rem,12vw,8rem); | |
| text-align:center; | |
| color:var(--gold); | |
| margin:100px 0 140px; | |
| letter-spacing:4px; | |
| text-shadow:0 6px 20px rgba(0,0,0,0.8); | |
| position:relative; | |
| } | |
| h1::after{ | |
| content:''; | |
| position:absolute; | |
| left:50%;bottom:-50px; | |
| transform:translateX(-50%); | |
| width:320px;height:6px; | |
| background:linear-gradient(90deg,transparent,var(--gold),#E8C56A,var(--gold),transparent); | |
| border-radius:4px; | |
| box-shadow:0 0 20px rgba(212,175,55,0.8); | |
| } | |
| .container{max-width:1400px;margin:0 auto;padding:0 20px} | |
| .register-form{ | |
| display:grid; | |
| grid-template-columns:repeat(3,1fr); | |
| gap:32px; | |
| max-width:1100px; | |
| margin:120px auto 100px; | |
| } | |
| .register-form input{ | |
| padding:28px 36px; | |
| font-size:1.6em; | |
| font-family:inherit; | |
| background:var(--surface); | |
| color:var(--cream); | |
| border:2px solid rgba(212,175,55,0.35); | |
| border-radius:20px; | |
| box-shadow:var(--shadow); | |
| transition:var(--transition); | |
| } | |
| .register-form input:focus{ | |
| outline:none; | |
| border-color:var(--gold); | |
| box-shadow:0 0 50px rgba(212,175,55,0.6); | |
| } | |
| .register-form button{ | |
| grid-column:1/-1; | |
| background:linear-gradient(135deg,var(--gold),#B8860B); | |
| color:#0F0A05; | |
| font-size:2em; | |
| font-weight:700; | |
| padding:32px; | |
| border:none; | |
| border-radius:22px; | |
| cursor:pointer; | |
| box-shadow:var(--shadow); | |
| transition:var(--transition); | |
| } | |
| .register-form button:hover{ | |
| transform:translateY(-16px); | |
| box-shadow:0 40px 80px rgba(212,175,55,0.4); | |
| } | |
| .buttons{ | |
| display:flex; | |
| justify-content:center; | |
| margin:80px 0; | |
| } | |
| button{ | |
| position:relative; | |
| background:var(--coffee); | |
| color:var(--cream); | |
| border:none; | |
| padding:40px 80px; | |
| font-size:1.9em; | |
| font-weight:600; | |
| letter-spacing:3px; | |
| text-transform:uppercase; | |
| border-radius:22px; | |
| cursor:pointer; | |
| overflow:hidden; | |
| box-shadow:var(--shadow); | |
| transition:var(--transition); | |
| } | |
| button::before{ | |
| content:''; | |
| position:absolute; | |
| inset:0; | |
| background:radial-gradient(circle at var(--x,50%) var(--y,50%), rgba(212,175,55,0.45), transparent 70%); | |
| opacity:0; | |
| transition:opacity .5s; | |
| } | |
| button:hover::before{opacity:1} | |
| button:hover{transform:translateY(-16px);box-shadow:0 40px 80px rgba(0,0,0,0.7)} | |
| .result-card{ | |
| background:var(--surface); | |
| border-radius:28px; | |
| padding:70px; | |
| margin:100px auto; | |
| max-width:1200px; | |
| box-shadow:var(--shadow); | |
| border:1px solid rgba(212,175,55,0.25); | |
| display:none; | |
| } | |
| .title{ | |
| font-family:'Playfair Display',serif; | |
| font-size:3.5em; | |
| text-align:center; | |
| color:var(--gold); | |
| margin-bottom:60px; | |
| letter-spacing:3px; | |
| } | |
| pre{ | |
| background:rgba(15,10,5,0.9); | |
| color:var(--cream); | |
| padding:50px; | |
| border-radius:20px; | |
| font-size:1.3em; | |
| line-height:2.2; | |
| border:1px solid rgba(212,175,55,0.3); | |
| box-shadow:inset 0 12px 40px rgba(0,0,0,0.7); | |
| } | |
| @media (max-width:900px){ | |
| .register-form{grid-template-columns:1fr;gap:24px} | |
| .buttons button{font-size:1.6em;padding:36px 60px} | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment