스프링

 

 

 

소스 https://github.com/braverokmc79/restapi-spring-boot-study

 

 

1.라이브러리 추가

spring-boot-starter-data-jpa
h2
lombok
validation
hateoas
springdoc-openapi-starter-webmvc-ui

 

예) pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.1.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>restfull-web-service</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>restfull-web-service</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<scope>runtime</scope>
		</dependency>


		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>



		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
			<version>2.14.2</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-hateoas</artifactId>
		</dependency>



		<!-- Swagger   적용
		  Swagger 3.0.0부턴 1개의 종속성만 추가해도 된다.
		 -->
		<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
			<version>2.2.0</version>
		</dependency>


		<!--- actuator -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>


		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-rest-hal-explorer</artifactId>
		</dependency>


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>


		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>


	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

 

 

 

 

2. application.yml 설정 예 

server:
  port: 8088


spring:
  # H2 Setting Info (H2 Console에 접속하기 위한 설정정보 입력)
  #h2:
  # console:
  #   enabled: false  # H2 Console을 사용할지 여부 (H2 Console은 H2 Database를 UI로 제공해주는 기능)
  #   path: /h2-console  # H2 Console의 Path
  # Database Setting Info (Database를 H2로 사용하기 위해 H2연결 정보 입력)
  datasource:
    driver-class-name: org.h2.Driver  # Database를 H2로 사용하겠다.
    url: jdbc:h2:tcp://localhost/~/test  # H2 접속 정보
    username: sa  # H2 접속 시 입력할 username 정보 (원하는 것으로 입력)
    password:  # H2 접속 시 입력할 password 정보 (원하는 것으로 입력)




  output:
     ansi:
         enabled: always

  devtools:
    livereload:
      enabled: true
    restart:
      enabled: true

  messages:
    basename : messages

  # JPA 설정
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    hibernate:
      ddl-auto: create        # DB 초기화 전략 (none, create, create-drop, update, validate)
    properties:
      hibernate:
        dialect: org.hibernate.dialect.H2Dialect
        format_sql: true      # 쿼리 로그 포맷 (정렬)
        show_sql: true        # 쿼리 로그 출력
    defer-datasource-initialization: true


  sql:
    init:
      mode: always



logging:
  level:
    org.springframework: info



springdoc:
  packages-to-scan: com.example.restfullwebservice
  default-consumes-media-type: application/json;charset=UTF-8
  default-produces-media-type: application/json;charset=UTF-8
  swagger-ui:
    path: /
    disable-swagger-default-url: true
    display-request-duration: true
    operations-sorter: alpha

#
#management:
#  endpoints:
#    web:
#      exposure:
#        include: "*"



 

 

스프링부트  3.0  변경사항

https://katastrophe.tistory.com/160

 

3. 목록 출력

controller

package com.example.restfullwebservice.user;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Optional;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;

@RestController
@RequestMapping("/jpa")
public class UserJpaController {

    @Autowired
    private UserRepository userRepository;


    // http://localhost:8088/jpa/users   or http://localhost:8088/users
    @GetMapping("/users")
    public List<User>  retrieveAllUsers(){
        return userRepository.findAll();

    }


    /**
     * [Spring] RestAPI와 Hateoas로 링크 삽입하기*
     *
     * https://katastrophe.tistory.com/160
     * @param id
     * @return
     *
     *
     * http://localhost:8088/jpa/users/1
     * 
   
     */

    @GetMapping("/users/{id}")
    public EntityModel<User> retrieveUser(@PathVariable  int id){
        Optional<User> user =userRepository.findById(id);

        if(user.isEmpty()){
            throw new UserNotFoundException(String.format("ID[%s] not found", id));
        }

       // Resource
        EntityModel<User> userEntityModel=EntityModel.of(user.get());
        WebMvcLinkBuilder linkTo= linkTo(methodOn(this.getClass()).retrieveAllUsers());
        userEntityModel.add(linkTo.withRel("all-users"));

        return userEntityModel;
    }






}

 

 

* 출력 예* 출력 예

  
     *
     * {
     *     "name": "User1",
     *     "joinDate": "2023-11-13T15:00:00.000+00:00",
     *     "ssn": "701010-11111",
     *     "_links": {
     *         "all-users": {
     *             "href": "http://localhost:8088/jpa/users"
     *         }
     *     }
     * }

 

 

 

4.삭제

    /**
     * 삭제
     * @param id
     */
    @DeleteMapping("/users/{id}")
    public void deleteUser(@PathVariable int id){
        log.info("**** deleteUser");
        userRepository.deleteById(id);
    }

 

 

 

5.등록

    /** 등록
     * insert into tbl_user (join_date,name,password,ssn,id) values (?,?,?,?,?)
     * @param user
     * @return
     */
    @PostMapping("/users")
    public ResponseEntity<?> createUser(@Valid @RequestBody User user){

        User  savedUser=userRepository.save(user);

        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedUser.getId())
                .toUri();

        ResponseEntity<User> build = ResponseEntity.created(location).build();
        log.info("** 유저 등록  : {}" , build);
        //return ResponseEntity.status(HttpStatus.CREATED).body(build.toString());
        return build;
    }

 

{
"name": "User5",
"joinDate": "2023-11-14T15:00:00.000+00:00",
"password" :"1111",
"ssn": "411010-11111"
}

 

 

 

 

 

6.게시를 작성자 정보 가져오기

 

    //게시글 및 작성자 정보 가져오기
    //
    // http://localhost:8088/jpa/users/1/posts
    /**
     *
     * http://localhost:8088/jpa/users/1/posts
     * @param id
     * @return
     */
    @GetMapping("/users/{id}/posts")
    public List<Post> retrieveAllPostsByUser(@PathVariable int id ){
        Optional<User> user= userRepository.findById(id);

        if(user.isEmpty()){
            throw new UserNotFoundException(String.format("ID[%s} not found", id));
        }

        return 

 

/** 출력 =>
 * [
 *     {
 *         "id": 1,
 *         "description": "My first post"
 *     },
 *     {
 *         "id": 2,
 *         "description": "My second post"
 *     }
 * ]
 *
 *
 */

 

 

 

 

 

7.게시물작성

    /**
     *게시물 저장
     * http://localhost:8088/jpa/users/{id}/posts
     * http://localhost:8088/jpa/users/1/posts
     */
    @PostMapping("/users/{id}/posts")
    public ResponseEntity<?> createPost( @PathVariable int id,  @Valid @RequestBody Post post){
        Optional<User> user= userRepository.findById(id);

        if(user.isEmpty()){
            throw new UserNotFoundException(String.format("ID[%s} not found", id));
        }

        post.setUser(user.get());
        Post savedPost = postRepository.save(post);


        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedPost.getId())
                .toUri();

        return ResponseEntity.created(location).build();
    }
    /**
     * 샘플 저장
     * {
     *
     *        "description":"Hello"
     *
     * }
     */

 

 

 

Post

package com.example.restfullwebservice.user;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
public class Post {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "POST_ID")
    private Integer id;


    private String description;


    // User : Post  -> 1 : (0 :N), Main : Sub -> Parent -> Child
    @ManyToOne(fetch = FetchType.LAZY)
    @JsonIgnore
    private User user;







}

 

 

User

package com.example.restfullwebservice.user;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.*;
import jakarta.validation.constraints.Past;
import jakarta.validation.constraints.Size;
import lombok.*;
import org.springframework.context.annotation.Primary;

import java.util.Date;
import java.util.List;

@Entity
@Getter
@Setter
@JsonIgnoreProperties(value = {"password" })
//@JsonFilter("UserInfo")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString
@EqualsAndHashCode(of="id")
@Schema(description = "사용자 상세 정보를 위한 도메인 객체")
@Table(name = "TBL_USER")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;


    @Size(min=2, message = "Name 은 2글자 이상 입력해 주세요.")
    @Schema(description = "사용자 이름을 입력해 주세요.")
    private String name;



    //과거데이터만 올수 있는 제약 조건
    @Past
    @Schema(description = "사용자 등록일을 입력해 주세요.")
    private Date joinDate;

//  @JsonIgnore
    @Schema(description = "사용자 패스워드를  입력해 주세요.")
    private String password;

  //  @JsonIgnore
   @Schema(description = "사용자 주민번호를   입력해 주세요.")
    private String ssn;


   @OneToMany(mappedBy = "user")
   private List<Post> posts;



    @Builder
    public User(Integer id, String name, Date joinDate, String password, String ssn){
        this.id=id;
        this.name=name;
        this.joinDate=joinDate;
        this.password=password;
        this.ssn=ssn;
    }



}

 

 

전체 controller 내용

package com.example.restfullwebservice.user;



import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.net.URI;
import java.util.List;
import java.util.Optional;

import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;

@RestController
@RequestMapping("/jpa")
@Slf4j
public class UserJpaController {

    @Autowired
    private UserRepository userRepository;


    @Autowired
    private PostRepository postRepository;

    // http://localhost:8088/jpa/users   or http://localhost:8088/users
    @GetMapping("/users")
    public List<User>  retrieveAllUsers(){
        return userRepository.findAll();

    }


    /**
     * [Spring] RestAPI와 Hateoas로 링크 삽입하기*
     *
     * https://katastrophe.tistory.com/160
     * @param id
     * @return
     *
     *
     * http://localhost:8088/jpa/users/1
     * 
     * 출력 예
     *
     * {
     *     "name": "User1",
     *     "joinDate": "2023-11-13T15:00:00.000+00:00",
     *     "ssn": "701010-11111",
     *     "_links": {
     *         "all-users": {
     *             "href": "http://localhost:8088/jpa/users"
     *         }
     *     }
     * }
     */

    @GetMapping("/users/{id}")
    public EntityModel<User> retrieveUser(@PathVariable  int id){
        Optional<User> user =userRepository.findById(id);

        if(user.isEmpty()){
            throw new UserNotFoundException(String.format("ID[%s] not found", id));
        }

       // Resource
        EntityModel<User> userEntityModel=EntityModel.of(user.get());
        WebMvcLinkBuilder linkTo= linkTo(methodOn(this.getClass()).retrieveAllUsers());
        userEntityModel.add(linkTo.withRel("all-users"));

        return userEntityModel;
    }


    /**
     * 삭제
     * @param id
     */
    @DeleteMapping("/users/{id}")
    public void deleteUser(@PathVariable int id){
        log.info("**** deleteUser");
        userRepository.deleteById(id);
    }


    
    /** 등록
     * insert into tbl_user (join_date,name,password,ssn,id) values (?,?,?,?,?)
     * @param user
     * @return
     */
    @PostMapping("/users")
    public ResponseEntity<?> createUser(@Valid @RequestBody User user){

        User  savedUser=userRepository.save(user);

        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedUser.getId())
                .toUri();

        ResponseEntity<User> build = ResponseEntity.created(location).build();
        log.info("** 유저 등록  : {}" , build);
        //return ResponseEntity.status(HttpStatus.CREATED).body(build.toString());
        return build;
    }



    //게시글 및 작성자 정보 가져오기
    //
    // http://localhost:8088/jpa/users/1/posts
    /**
     *
     * http://localhost:8088/jpa/users/1/posts
     * @param id
     * @return
     */
    @GetMapping("/users/{id}/posts")
    public List<Post> retrieveAllPostsByUser(@PathVariable int id ){
        Optional<User> user= userRepository.findById(id);

        if(user.isEmpty()){
            throw new UserNotFoundException(String.format("ID[%s} not found", id));
        }

        return user.get().getPosts();
    }


/** 출력 =>
 * [
 *     {
 *         "id": 1,
 *         "description": "My first post"
 *     },
 *     {
 *         "id": 2,
 *         "description": "My second post"
 *     }
 * ]
 *
 *
 */


    /**
     *게시물 저장
     * http://localhost:8088/jpa/users/{id}/posts
     * http://localhost:8088/jpa/users/1/posts
     */
    @PostMapping("/users/{id}/posts")
    public ResponseEntity<?> createPost( @PathVariable int id,  @Valid @RequestBody Post post){
        Optional<User> user= userRepository.findById(id);

        if(user.isEmpty()){
            throw new UserNotFoundException(String.format("ID[%s} not found", id));
        }

        post.setUser(user.get());
        Post savedPost = postRepository.save(post);


        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(savedPost.getId())
                .toUri();

        return ResponseEntity.created(location).build();
    }

    /**
     * 샘플 저장
     * {
     *
     *        "description":"Hello"
     *
     * }
     */






}

 

 

 

 

 

about author

PHRASE

Level 60  라이트

사람이 자신이 하는 일에 열중할 때 행복은 자연히 따라온다. 무슨 일이든 지금 하고 있는 일에 몰두하라. 그것이 위대한 일인지 아닌지는 생각하지 말고, 방을 청소할 때는 완전히 청소에 몰두하고, 요리할 때는 거기에만 몰두하라. -라즈니쉬

댓글 ( 4)

댓글 남기기

작성

스프링 목록    more