Intro
In this time, I will create a web application with Spring Boot.
Adding a Thymeleaf page
First, I will add pages to access web APIs.
To use Thymeleaf, I add "org.springframework.boot:spring-boot-starter-thymeleaf" into build.gradle.
build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.1.5' id 'io.spring.dependency-management' version '1.1.3' } group = 'jp.masanori' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() }
I can put an HTML file as Thymeleaf template file into src/main/resources/templates.
index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <title>Hello</title> <meta charset="utf-8"> </head> <body> <h1>Hello world!</h1> <p class="template_value" th:text="|Hello ${name}!!!|" /> <button onclick="IndexPage.getKey()">Get key</button> <script src="/js/index.page.js"></script> <script>IndexPage.init("Hello world!");</script> </body> </html>
The controller class should has a "@Controller" anotation.
PageController.java
package jp.masanori.springbootsample; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class PageController { @GetMapping("/") public String hello(@RequestParam(value = "name", defaultValue = "World") String name, Model model) { model.addAttribute("name", name); return "index"; } }
I put JavaScript files and CSS files into src/main/resources/static as static files.
CORS
I will try getting string data from another Spring Boot application(localhost:8081).
[localhost:8080] index.page.ts
window.IndexPage = { init(message: string) { console.log(message); }, getKey() { fetch("http://localhost:8081/key", { mode: "cors", "method": "GET" }).then(res => res.text()) .then(res => console.log(res)) .catch(err => console.error(err)); } }
[localhost:8081] ApiController.java
package jp.masanori.corssample.controllers; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ApiController { private static final String ALGORITHM = "HmacSHA256"; @GetMapping("/key") public String getKey() { String key = generateKey(); return key; } private String generateKey() { try { DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss SSS"); String currentTime = LocalDateTime.now().format(dateFormat); Mac sha256 = Mac.getInstance(ALGORITHM); sha256.init(new SecretKeySpec(currentTime.getBytes("UTF-8"), ALGORITHM)); var base64 = Base64.getEncoder(); return base64.encodeToString(sha256.doFinal(currentTime.getBytes("UTF-8"))); } catch (NoSuchAlgorithmException ex) { System.out.println(ex.getMessage()); } catch (InvalidKeyException ex) { System.out.println(ex.getMessage()); } catch (UnsupportedEncodingException ex) { System.out.println(ex.getMessage()); } return ""; } }
But my request is blocked by CORS error.
Access to fetch at 'http://localhost:8081/key' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
To resolve the error, I add configurations of CORS into the Spring Boot projects.
[localhost:8081] CorsConfigurer.java
package jp.masanori.corssample.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfigurer implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/*") .allowedOrigins("http://localhost:8080", "http://localhost:8081") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTION") .allowedHeaders("*") // To set custom headers .exposedHeaders("Sample-Key") .allowCredentials(false).maxAge(3600); } }
- CORS support in Spring Framework
- Getting Started|Enabling Cross Origin Requests for a RESTful Web Service
Getting parameters
I can get data what are sent from clients by annotations.
URL params
[localhost:8081] ApiController.java
... @GetMapping("/params") public String getUrlParams(@RequestParam(value = "name") String name, @RequestParam(value = "message") String message) { return String.format("Name: %s Message: %s", name, message); } ...
Request URL
http://localhost:8081/params?name=masa&message=hello+world
Request Body
[localhost:8080] index.page.ts
... sendMessage() { const message = { name: "masa", message: "hello world" }; fetch("http://localhost:8081/params", { mode: "cors", method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(message), }).then(res => res.text()) .then(res => { console.log(res); }).catch(err => console.error(err)); } }
[localhost:8081] ApiController.java
... @PostMapping("/params") public String getBodyParams(@RequestBody SampleMessage message) { return String.format("Name: %s Message: %s", message.getName(), message.getMessage()); } ...
Top comments (0)