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)