2021-08-07

This commit is contained in:
2021-08-07 11:30:31 +09:00
parent 7bb5ca68c1
commit 50f83e3fa0
36 changed files with 667 additions and 8 deletions

31
cache/build.gradle.kts vendored Normal file
View File

@@ -0,0 +1,31 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
plugins {
id("elex-spring-boot")
id("org.springframework.boot") version "2.5.3"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-mustache")
implementation("org.springframework.boot:spring-boot-starter-cache")
implementation ("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("com.h2database:h2")
compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-devtools")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}

View File

@@ -0,0 +1,45 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Component;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Component
public class MyRunner implements CommandLineRunner {
@Autowired
private PersonRepository repository;
@Override
public void run(String... args) throws Exception {
repository.deleteAll();
Person charlie = new Person();
charlie.setName("Charlie");
charlie.setAge(11);
repository.save(charlie);
Person steve = new Person();
steve.setName("Steve");
steve.setAge(34);
repository.save(steve);
}
}
}

View File

@@ -0,0 +1,9 @@
package kr.pe.elex.examples;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
@Slf4j
@Configuration
public class Config {
}

View File

@@ -0,0 +1,34 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Slf4j
@RestController
public class MyController {
@Autowired
private MyService service;
@GetMapping(path = {"/{id}"})
public ResponseEntity<Person> index(@PathVariable Long id) {
return ResponseEntity.of(service.getItem(id));
}
}

View File

@@ -0,0 +1,28 @@
package kr.pe.elex.examples;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Slf4j
@Service
public class MyService {
@Autowired
private PersonRepository repository;
@Cacheable("person")
public Optional<Person> getItem(long at) {
log.info("Calling a repository method!");
return repository.findById(at);
}
public void addItem(Person item) {
repository.save(item);
}
}

View File

@@ -0,0 +1,18 @@
package kr.pe.elex.examples;
import lombok.*;
import javax.persistence.*;
@Entity
@Getter @Setter @ToString
@NoArgsConstructor @AllArgsConstructor
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column
private String name;
@Column
private int age;
}

View File

@@ -0,0 +1,8 @@
package kr.pe.elex.examples;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}

View File

@@ -0,0 +1,8 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;

View File

@@ -0,0 +1,17 @@
spring:
application:
name: My spring-boot project
mustache:
expose-request-attributes: true
h2:
console:
enabled: true
datasource:
url: jdbc:h2:mem:testdb
driverClassName: org.h2.Driver
username: sa
password: pw
jpa:
database-platform: org.hibernate.dialect.H2Dialect
server:
port: 8080

10
cache/src/main/resources/banner.txt vendored Normal file
View File

@@ -0,0 +1,10 @@
('-. ('-. ) (`-.
_( OO) _( OO) ( OO ).
(,------.,--. (,------.(_/. \_)-.
| .---'| |.-') | .---' \ `.' /
| | | | OO ) | | \ /\
(| '--. | |`-' |(| '--. \ \ |
| .--'(| '---.' | .--' .' \_)
| `---.| | | `---. / .'. \
`------'`------' `------''--' '--'
powered by ELEX

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Spring-boot Examples
~
~ Copyright (c) 2021. Elex. All Rights Reserved.
~ https://www.elex-project.com/
-->
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<springProperty name="LOG_DIR" source="logging.path"
defaultValue="${user.home}/logs"/>
<property name="LOG_PATH" value="${LOG_DIR}/stephanie.log"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="ROLLING-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<charset>UTF-8</charset>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/sebastian_%d{yyyy-MM-dd}_%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>60</maxHistory>
</rollingPolicy>
</appender>
<logger name="kr.pe.elex" level="debug" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING-FILE"/>
</logger>
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING-FILE"/>
</root>
</configuration>

View File

@@ -0,0 +1,15 @@
<h1>File Upload Example!!!</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<label for="file">Select a file: </label>
<input id="file" name="file" type="file" title="Upload"/>
<div>
<button>Upload</button>
</div>
</form>
<h2>Uploaded Files</h2>
<p>Click to download.</p>
<ul>
{{#files}}
<li><a href="/files/{{.}}">{{.}}</a></li>
{{/files}}
</ul>

35
rest-doc/build.gradle.kts Normal file
View File

@@ -0,0 +1,35 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
plugins {
id("elex-spring-boot")
id("org.springframework.boot") version "2.5.3"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
id("org.asciidoctor.jvm.convert") version "3.3.0"
}
tasks.asciidoctor {
setSourceDir(File("src/main/asciidoc"))
attributes(mapOf(
"snippets" to "target/snippets"
))
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-mustache")
compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-devtools")
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
}

View File

@@ -0,0 +1,11 @@
= Getting Started With Spring REST Docs
This is an example output for a service running at http://localhost:8080:
.request
include::{snippets}/home/http-request.adoc[]
.response
include::{snippets}/home/http-response.adoc[]
As you can see the format is very simple, and in fact you always get the same message.

View File

@@ -0,0 +1,25 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public MyService service(){
return new MyService();
}
}

View File

@@ -0,0 +1,38 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.util.Set;
@Slf4j
@RestController
public class MyController {
@Autowired
private MyService service;
@GetMapping(path = {"/name/{name}"})
public ResponseEntity<Person> getPerson(@PathVariable String name) {
return ResponseEntity.ok(service.getPerson(name));
}
}

View File

@@ -0,0 +1,32 @@
package kr.pe.elex.examples;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;
@Slf4j
@Service
public class MyService {
private Set<Person> data;
@PostConstruct
private void init() {
data = new HashSet<>();
data.add(new Person("Charlie", 11));
}
public Person getPerson(String name) {
for (Person person : data) {
if (person.getName().equals(name)) {
return person;
}
}
return null;
}
public void addPerson(Person person){
data.add(person);
}
}

View File

@@ -0,0 +1,13 @@
package kr.pe.elex.examples;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private int age;
}

View File

@@ -0,0 +1,8 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
package kr.pe.elex.examples;

View File

@@ -0,0 +1,5 @@
spring:
application:
name: My spring-boot project
server:
port: 8080

View File

@@ -0,0 +1,10 @@
('-. ('-. ) (`-.
_( OO) _( OO) ( OO ).
(,------.,--. (,------.(_/. \_)-.
| .---'| |.-') | .---' \ `.' /
| | | | OO ) | | \ /\
(| '--. | |`-' |(| '--. \ \ |
| .--'(| '---.' | .--' .' \_)
| `---.| | | `---. / .'. \
`------'`------' `------''--' '--'
powered by ELEX

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Spring-boot Examples
~
~ Copyright (c) 2021. Elex. All Rights Reserved.
~ https://www.elex-project.com/
-->
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<springProperty name="LOG_DIR" source="logging.path"
defaultValue="${user.home}/logs"/>
<property name="LOG_PATH" value="${LOG_DIR}/stephanie.log"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="ROLLING-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<charset>UTF-8</charset>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_PATH}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/sebastian_%d{yyyy-MM-dd}_%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>60</maxHistory>
</rollingPolicy>
</appender>
<logger name="kr.pe.elex" level="debug" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING-FILE"/>
</logger>
<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING-FILE"/>
</root>
</configuration>

View File

@@ -0,0 +1,15 @@
<h1>File Upload Example!!!</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<label for="file">Select a file: </label>
<input id="file" name="file" type="file" title="Upload"/>
<div>
<button>Upload</button>
</div>
</form>
<h2>Uploaded Files</h2>
<p>Click to download.</p>
<ul>
{{#files}}
<li><a href="/files/{{.}}">{{.}}</a></li>
{{/files}}
</ul>

View File

@@ -0,0 +1,39 @@
package kr.pe.elex.examples;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import java.util.HashSet;
import java.util.Set;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.payload.PayloadDocumentation.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(MyController.class)
@AutoConfigureRestDocs(outputDir = "target/snippets")
public class WebLayerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void defaultPage() throws Exception {
this.mockMvc.perform(
get("/name/{name}", "Charlie"))
.andDo(print())
.andExpect(status().isOk())
.andDo(document("home",
responseFields(fieldWithPath("name").description("Name..."),
fieldWithPath("age").description("Age..."))
));
}
}

View File

@@ -0,0 +1,4 @@
[source,bash]
----
$ curl 'http://localhost:8080/name/Charlie' -i -X GET
----

View File

@@ -0,0 +1,6 @@
[source,http,options="nowrap"]
----
GET /name/Charlie HTTP/1.1
Host: localhost:8080
----

View File

@@ -0,0 +1,8 @@
[source,http,options="nowrap"]
----
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 27
{"name":"Charlie","age":11}
----

View File

@@ -0,0 +1,4 @@
[source,bash]
----
$ http GET 'http://localhost:8080/name/Charlie'
----

View File

@@ -0,0 +1,4 @@
[source,options="nowrap"]
----
----

View File

@@ -0,0 +1,4 @@
[source,options="nowrap"]
----
{"name":"Charlie","age":11}
----

View File

@@ -0,0 +1,12 @@
|===
|Path|Type|Description
|`+name+`
|`+String+`
|Name...
|`+age+`
|`+Number+`
|Age...
|===

View File

@@ -0,0 +1,33 @@
/*
* Spring-boot Examples
*
* Copyright (c) 2021. Elex. All Rights Reserved.
* https://www.elex-project.com/
*/
plugins {
id("elex-spring-boot")
id("org.springframework.boot") version "2.5.3"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-mustache")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation ("org.springframework.boot:spring-boot-starter-security")
testImplementation ("org.springframework.security:spring-security-test")
implementation ("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("com.h2database:h2")
compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-devtools")
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}

View File

@@ -6,5 +6,8 @@
*/
rootProject.name = "spring-boot-examples"
include("file-upload", "security", "security-with-jpa", "validation", "testing",
"mqtt", "websocket", "restful", "swing")
include(
"file-upload", "security", "security-with-jpa", "validation", "testing",
"mqtt", "websocket", "restful", "swing", "rest-doc",
"cache", "security-with-jwt"
)

View File

@@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.swing.*;
import java.awt.*;
@@ -13,17 +14,20 @@ public class MyPanel extends JPanel {
@Autowired
private MyService service;
@Autowired
private MyToolbar toolbar;
public MyPanel() {
super();
@PostConstruct
private void init(){
this.setLayout(new BorderLayout());
JButton btn = new JButton("Button");
this.add(new JLabel("Hello"), BorderLayout.CENTER);
this.add(btn, BorderLayout.SOUTH);
this.add(toolbar, BorderLayout.NORTH);
btn.addActionListener(e -> {
System.out.println(service.getText());
System.out.println(service.getSomething());
});
}
}

View File

@@ -1,11 +1,16 @@
package kr.pe.elex.examples;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Service;
@Service
public class MyService {
public String getText(){
@Getter @Setter
private String something = "Something";
public String getText() {
return "Hello~";
}
}

View File

@@ -0,0 +1,22 @@
package kr.pe.elex.examples;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.swing.*;
@Component
public class MyToolbar extends JToolBar {
@Autowired
private MyService service;
@PostConstruct
private void init(){
this.add(new JLabel(service.getSomething()));
service.setSomething("changed by Toolbar");
}
}