DEV Community

Masui Masanori
Masui Masanori

Posted on

1

Try Spring Boot

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()
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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";
    }
}
Enter fullscreen mode Exit fullscreen mode

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));
    }
}
Enter fullscreen mode Exit fullscreen mode

[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 "";
    }
}
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
    }
...
Enter fullscreen mode Exit fullscreen mode

Request URL

http://localhost:8081/params?name=masa&message=hello+world
Enter fullscreen mode Exit fullscreen mode

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));
    }
}
Enter fullscreen mode Exit fullscreen mode

[localhost:8081] ApiController.java

...
    @PostMapping("/params")
    public String getBodyParams(@RequestBody SampleMessage message) {
        return String.format("Name: %s Message: %s", message.getName(), message.getMessage());
    }
...
Enter fullscreen mode Exit fullscreen mode

Image of Bright Data

Overcome Captchas with Ease – Keep your data flow uninterrupted.

Our Web Unlocker smoothly handles captchas, ensuring your data scraping activities remain productive.

Solve Captchas

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay