├── .gitignore ├── build.gradle ├── data-rest └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── community │ │ │ └── rest │ │ │ ├── DataRestApplication.java │ │ │ ├── controller │ │ │ └── BoardRestController.java │ │ │ ├── domain │ │ │ ├── Board.java │ │ │ ├── User.java │ │ │ ├── enums │ │ │ │ ├── BoardType.java │ │ │ │ └── SocialType.java │ │ │ └── projection │ │ │ │ ├── BoardOnlyContainTitle.java │ │ │ │ └── UserOnlyContainName.java │ │ │ ├── event │ │ │ └── BoardEventHandler.java │ │ │ └── repository │ │ │ ├── BoardRepository.java │ │ │ └── UserRepository.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── community │ └── rest │ ├── BoardEventTest.java │ └── DataRestApplicationTests.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── rest-web └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── community │ │ │ └── rest │ │ │ ├── RestWebApplication.java │ │ │ ├── controller │ │ │ └── BoardRestController.java │ │ │ ├── domain │ │ │ ├── Board.java │ │ │ ├── User.java │ │ │ └── enums │ │ │ │ ├── BoardType.java │ │ │ │ └── SocialType.java │ │ │ └── repository │ │ │ ├── BoardRepository.java │ │ │ └── UserRepository.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── community │ └── rest │ └── RestWebApplicationTests.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | /out 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | 20 | ### NetBeans ### 21 | nbproject/private/ 22 | build/ 23 | nbbuild/ 24 | dist/ 25 | nbdist/ 26 | .nb-gradle/ -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.0.3.RELEASE' 4 | } 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 10 | } 11 | } 12 | 13 | subprojects { 14 | apply plugin: 'java' 15 | apply plugin: 'eclipse' 16 | apply plugin: 'org.springframework.boot' 17 | apply plugin: 'io.spring.dependency-management' 18 | 19 | group = 'com.rest' 20 | version = '0.0.1-SNAPSHOT' 21 | sourceCompatibility = 1.8 22 | 23 | repositories { 24 | mavenCentral() 25 | } 26 | 27 | dependencies { 28 | compile('org.springframework.boot:spring-boot-starter-data-jpa') 29 | compile('org.springframework.boot:spring-boot-starter-security') 30 | compile('com.fasterxml.jackson.datatype:jackson-datatype-jsr310') 31 | compile('org.springframework.data:spring-data-rest-hal-browser') 32 | 33 | runtime('org.springframework.boot:spring-boot-devtools') 34 | runtime('mysql:mysql-connector-java') 35 | runtime('com.h2database:h2') 36 | compileOnly('org.projectlombok:lombok') 37 | testCompile('org.springframework.boot:spring-boot-starter-test') 38 | testCompile('org.springframework.security:spring-security-test') 39 | } 40 | } 41 | 42 | project(':data-rest') { 43 | dependencies { 44 | compile('org.springframework.boot:spring-boot-starter-data-rest') { 45 | exclude module: "jackson-databind" 46 | } 47 | } 48 | } 49 | 50 | project(':rest-web') { 51 | dependencies { 52 | compile('org.springframework.boot:spring-boot-starter-web') { 53 | exclude module: "jackson-databind" 54 | } 55 | compile('org.springframework.boot:spring-boot-starter-hateoas') 56 | } 57 | } -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/DataRestApplication.java: -------------------------------------------------------------------------------- 1 | package com.community.rest; 2 | 3 | import com.community.rest.event.BoardEventHandler; 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 13 | import org.springframework.security.core.userdetails.User; 14 | import org.springframework.security.core.userdetails.UserDetails; 15 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 16 | import org.springframework.web.cors.CorsConfiguration; 17 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | @SpringBootApplication 23 | public class DataRestApplication { 24 | 25 | public static void main(String[] args) { 26 | SpringApplication.run(DataRestApplication.class, args); 27 | } 28 | 29 | @Configuration 30 | @EnableGlobalMethodSecurity(prePostEnabled = true) 31 | @EnableWebSecurity 32 | static class SecurityConfiguration extends WebSecurityConfigurerAdapter { 33 | 34 | @Bean 35 | InMemoryUserDetailsManager userDetailsManager() { 36 | User.UserBuilder commonUser = User.withUsername("commonUser").password("{noop}common").roles("USER"); 37 | User.UserBuilder havi = User.withUsername("havi").password("{noop}test").roles("USER", "ADMIN"); 38 | 39 | List userDetailsList = new ArrayList<>(); 40 | userDetailsList.add(commonUser.build()); 41 | userDetailsList.add(havi.build()); 42 | 43 | return new InMemoryUserDetailsManager(userDetailsList); 44 | } 45 | 46 | @Override 47 | protected void configure(HttpSecurity http) throws Exception { 48 | CorsConfiguration configuration = new CorsConfiguration(); 49 | configuration.addAllowedOrigin(CorsConfiguration.ALL); 50 | configuration.addAllowedMethod(CorsConfiguration.ALL); 51 | configuration.addAllowedHeader(CorsConfiguration.ALL); 52 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 53 | source.registerCorsConfiguration("/**", configuration); 54 | 55 | http.httpBasic() 56 | .and().authorizeRequests() 57 | //.antMatchers(HttpMethod.POST, "/Boards/**").hasRole("ADMIN") 58 | .anyRequest().permitAll() 59 | .and().cors().configurationSource(source) 60 | .and().csrf().disable(); 61 | } 62 | } 63 | 64 | @Bean 65 | BoardEventHandler boardEventHandler() { 66 | return new BoardEventHandler(); 67 | } 68 | 69 | /*@Configuration 70 | public class CustomizedRestMvcConfiguration extends RepositoryRestConfigurerAdapter { 71 | 72 | @Override 73 | public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { 74 | config.getProjectionConfiguration().addProjection(UserOnlyContainName.class); 75 | } 76 | }*/ 77 | 78 | } 79 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/controller/BoardRestController.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.controller; 2 | 3 | import com.community.rest.domain.Board; 4 | import com.community.rest.repository.BoardRepository; 5 | 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.data.rest.webmvc.RepositoryRestController; 9 | import org.springframework.data.web.PageableDefault; 10 | import org.springframework.hateoas.PagedResources; 11 | import org.springframework.hateoas.PagedResources.PageMetadata; 12 | import org.springframework.hateoas.Resources; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.ResponseBody; 16 | 17 | import java.util.List; 18 | 19 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; 20 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; 21 | 22 | @RepositoryRestController 23 | public class BoardRestController { 24 | 25 | private BoardRepository boardRepository; 26 | 27 | public BoardRestController(BoardRepository boardRepository) { 28 | this.boardRepository = boardRepository; 29 | } 30 | 31 | //url 규칙이 맞아야 리퀘스트가 들어옴 32 | @GetMapping("/boards/search/addTest") 33 | public @ResponseBody ResponseEntity basicTest() { 34 | List boardList = boardRepository.findAll(); 35 | 36 | Resources resources = new Resources<>(boardList); 37 | resources.add(linkTo(methodOn(BoardRestController.class).basicTest()).withSelfRel()); 38 | return ResponseEntity.ok(resources); 39 | } 40 | 41 | //오버라이드 42 | @GetMapping("/boards") 43 | public @ResponseBody Resources simpleBoard(@PageableDefault Pageable pageable) { 44 | Page boardList = boardRepository.findAll(pageable); 45 | 46 | PageMetadata pageMetadata = new PageMetadata(pageable.getPageSize(), boardList.getNumber(), boardList.getTotalElements()); 47 | PagedResources resources = new PagedResources<>(boardList.getContent(), pageMetadata); 48 | resources.add(linkTo(methodOn(BoardRestController.class).simpleBoard(pageable)).withSelfRel()); 49 | return resources; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/domain/Board.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain; 2 | 3 | 4 | import com.community.rest.domain.enums.BoardType; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.EnumType; 12 | import javax.persistence.Enumerated; 13 | import javax.persistence.FetchType; 14 | import javax.persistence.GeneratedValue; 15 | import javax.persistence.Id; 16 | import javax.persistence.OneToOne; 17 | import javax.persistence.Table; 18 | 19 | import lombok.Builder; 20 | import lombok.Getter; 21 | import lombok.NoArgsConstructor; 22 | 23 | /** 24 | * Created by KimYJ on 2017-07-12. 25 | */ 26 | @Getter 27 | @NoArgsConstructor 28 | @Entity 29 | @Table 30 | public class Board implements Serializable { 31 | 32 | @Id 33 | @Column 34 | @GeneratedValue 35 | private Long idx; 36 | 37 | @Column 38 | private String title; 39 | 40 | @Column 41 | private String subTitle; 42 | 43 | @Column 44 | private String content; 45 | 46 | @Column 47 | @Enumerated(EnumType.STRING) 48 | private BoardType boardType; 49 | 50 | @Column 51 | private LocalDateTime createdDate; 52 | 53 | @Column 54 | private LocalDateTime updatedDate; 55 | 56 | @OneToOne(fetch= FetchType.LAZY) 57 | private User user; 58 | 59 | @Builder 60 | public Board(String title, String subTitle, String content, BoardType boardType, LocalDateTime createdDate, LocalDateTime updatedDate, User user) { 61 | this.title = title; 62 | this.subTitle = subTitle; 63 | this.content = content; 64 | this.boardType = boardType; 65 | this.createdDate = createdDate; 66 | this.updatedDate = updatedDate; 67 | this.user = user; 68 | } 69 | 70 | public void setCreatedDateNow() { 71 | this.createdDate = LocalDateTime.now(); 72 | } 73 | 74 | public void setUpdatedDateNow() { 75 | this.updatedDate = LocalDateTime.now(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain; 2 | 3 | 4 | import com.community.rest.domain.enums.SocialType; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.EnumType; 13 | import javax.persistence.Enumerated; 14 | import javax.persistence.GeneratedValue; 15 | import javax.persistence.Id; 16 | import javax.persistence.Table; 17 | 18 | import lombok.Builder; 19 | import lombok.Getter; 20 | import lombok.NoArgsConstructor; 21 | 22 | /** 23 | * Created by KimYJ on 2017-07-12. 24 | */ 25 | @Getter 26 | @NoArgsConstructor 27 | @Entity 28 | @Table 29 | public class User implements Serializable { 30 | 31 | @Id 32 | @Column 33 | @GeneratedValue 34 | private Long idx; 35 | 36 | @Column 37 | private String name; 38 | 39 | @Column 40 | @JsonIgnore 41 | private String password; 42 | 43 | @Column 44 | private String email; 45 | 46 | @Column 47 | private String pincipal; 48 | 49 | @Column 50 | @Enumerated(EnumType.STRING) 51 | private SocialType socialType; 52 | 53 | @Column 54 | private LocalDateTime createdDate; 55 | 56 | @Column 57 | private LocalDateTime updatedDate; 58 | 59 | @Builder 60 | public User(String name, String password, String email, String pincipal, SocialType socialType, LocalDateTime createdDate, LocalDateTime updatedDate) { 61 | this.name = name; 62 | this.password = password; 63 | this.email = email; 64 | this.pincipal = pincipal; 65 | this.socialType = socialType; 66 | this.createdDate = createdDate; 67 | this.updatedDate = updatedDate; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/domain/enums/BoardType.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain.enums; 2 | 3 | /** 4 | * Created by KimYJ on 2017-07-12. 5 | */ 6 | public enum BoardType { 7 | notice("공지사항"), 8 | free("자유게시판"); 9 | 10 | private String value; 11 | 12 | BoardType(String value) { 13 | this.value = value; 14 | } 15 | 16 | public String getValue() { 17 | return this.value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/domain/enums/SocialType.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain.enums; 2 | 3 | public enum SocialType { 4 | FACEBOOK("facebook"), 5 | GOOGLE("google"), 6 | KAKAO("kakao"); 7 | 8 | private final String ROLE_PREFIX = "ROLE_"; 9 | private String name; 10 | 11 | SocialType(String name) { 12 | this.name = name; 13 | } 14 | 15 | public String getRoleType() { return ROLE_PREFIX + name.toUpperCase(); } 16 | 17 | public String getValue() { return name; } 18 | 19 | public boolean isEquals(String authority) { 20 | return this.getRoleType().equals(authority); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/domain/projection/BoardOnlyContainTitle.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain.projection; 2 | 3 | import com.community.rest.domain.Board; 4 | import org.springframework.data.rest.core.config.Projection; 5 | 6 | @Projection(name = "getOnlyTitle", types = { Board.class }) 7 | public interface BoardOnlyContainTitle { 8 | 9 | String getTitle(); 10 | } 11 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/domain/projection/UserOnlyContainName.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain.projection; 2 | 3 | import com.community.rest.domain.User; 4 | 5 | import org.springframework.data.rest.core.config.Projection; 6 | 7 | @Projection(name = "getOnlyName", types = { User.class }) 8 | public interface UserOnlyContainName { 9 | 10 | String getName(); 11 | } 12 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/event/BoardEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.event; 2 | 3 | import com.community.rest.domain.Board; 4 | 5 | import org.springframework.data.rest.core.annotation.HandleBeforeCreate; 6 | import org.springframework.data.rest.core.annotation.HandleBeforeSave; 7 | import org.springframework.data.rest.core.annotation.RepositoryEventHandler; 8 | 9 | @RepositoryEventHandler 10 | public class BoardEventHandler { 11 | 12 | @HandleBeforeCreate 13 | public void beforeCreateBoard(Board board) { 14 | board.setCreatedDateNow(); 15 | } 16 | 17 | @HandleBeforeSave 18 | public void beforeSaveBoard(Board board) { 19 | board.setUpdatedDateNow(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/repository/BoardRepository.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.repository; 2 | 3 | import com.community.rest.domain.Board; 4 | import com.community.rest.domain.projection.BoardOnlyContainTitle; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 9 | import org.springframework.data.rest.core.annotation.RestResource; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | 12 | import java.util.List; 13 | 14 | @RepositoryRestResource(excerptProjection = BoardOnlyContainTitle.class) 15 | public interface BoardRepository extends JpaRepository { 16 | 17 | @Override 18 | @PreAuthorize("hasRole('ROLE_ADMIN')") 19 | S save(S entity); 20 | 21 | @RestResource 22 | List findByTitle(@Param("title") String title); 23 | } 24 | -------------------------------------------------------------------------------- /data-rest/src/main/java/com/community/rest/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.repository; 2 | 3 | import com.community.rest.domain.User; 4 | import com.community.rest.domain.projection.UserOnlyContainName; 5 | 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 8 | 9 | @RepositoryRestResource(excerptProjection = UserOnlyContainName.class) 10 | public interface UserRepository extends JpaRepository { 11 | } 12 | -------------------------------------------------------------------------------- /data-rest/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:mysql://172.16.135.15:3306/autoconfiguration 4 | username: mns 5 | password: dltmxmdlsxjspt 6 | driver-class-name: com.mysql.jdbc.Driver 7 | data: 8 | rest: 9 | base-path: /api 10 | default-page-size: 10 11 | max-page-size: 10 12 | server: 13 | port: 8081 -------------------------------------------------------------------------------- /data-rest/src/test/java/com/community/rest/BoardEventTest.java: -------------------------------------------------------------------------------- 1 | package com.community.rest; 2 | 3 | import com.community.rest.domain.Board; 4 | 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.boot.test.web.client.TestRestTemplate; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | import static org.junit.Assert.assertNotNull; 13 | 14 | @RunWith(SpringRunner.class) 15 | @SpringBootTest(classes = DataRestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) 16 | @AutoConfigureTestDatabase 17 | public class BoardEventTest { 18 | private TestRestTemplate testRestTemplate = new TestRestTemplate("havi", "test"); 19 | 20 | @Test 21 | public void 저장할때_이벤트가_적용되어_생성날짜가_생성되는가() { 22 | Board createdBoard = createBoard(); 23 | assertNotNull(createdBoard.getCreatedDate()); 24 | } 25 | 26 | @Test 27 | public void 수정할때_이벤트가_적용되어_수정날짜가_생성되는가() { 28 | Board createdBoard = createBoard(); 29 | Board updatedBoard = updateBoard(createdBoard); 30 | assertNotNull(updatedBoard.getUpdatedDate()); 31 | } 32 | 33 | private Board createBoard() { 34 | Board board = Board.builder().title("저장 이벤트 테스트").build(); 35 | return testRestTemplate.postForObject("http://127.0.0.1:8081/api/boards", board, Board.class); 36 | } 37 | 38 | private Board updateBoard(Board createdBoard) { 39 | String updateUri = "http://127.0.0.1:8081/api/boards/1"; 40 | testRestTemplate.put(updateUri, createdBoard); 41 | return testRestTemplate.getForObject(updateUri, Board.class); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /data-rest/src/test/java/com/community/rest/DataRestApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.community.rest; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class DataRestApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/young891221/Spring-Boot-Community-Rest/d9b29eaf52ff378cec18dfb2534c188613e61dff/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Jul 10 15:59:51 KST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn ( ) { 37 | echo "$*" 38 | } 39 | 40 | die ( ) { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save ( ) { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/RestWebApplication.java: -------------------------------------------------------------------------------- 1 | package com.community.rest; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.core.userdetails.User; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 15 | import org.springframework.web.cors.CorsConfiguration; 16 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | @SpringBootApplication 22 | public class RestWebApplication { 23 | 24 | public static void main(String[] args) { 25 | SpringApplication.run(RestWebApplication.class, args); 26 | } 27 | 28 | @Configuration 29 | @EnableGlobalMethodSecurity(prePostEnabled = true) 30 | @EnableWebSecurity 31 | static class SecurityConfiguration extends WebSecurityConfigurerAdapter { 32 | 33 | @Bean 34 | InMemoryUserDetailsManager userDetailsManager() { 35 | User.UserBuilder commonUser = User.withUsername("commonUser"); 36 | User.UserBuilder havi = User.withUsername("havi"); 37 | 38 | List userDetailsList = new ArrayList<>(); 39 | userDetailsList.add(commonUser.password("{noop}common").roles("USER").build()); 40 | userDetailsList.add(havi.password("{noop}test").roles("USER", "ADMIN").build()); 41 | 42 | return new InMemoryUserDetailsManager(userDetailsList); 43 | } 44 | 45 | @Override 46 | protected void configure(HttpSecurity http) throws Exception { 47 | CorsConfiguration configuration = new CorsConfiguration(); 48 | configuration.addAllowedOrigin("*"); 49 | configuration.addAllowedMethod("*"); 50 | configuration.addAllowedHeader("*"); 51 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 52 | source.registerCorsConfiguration("/**", configuration); 53 | 54 | http.httpBasic() 55 | .and().authorizeRequests() 56 | //.antMatchers(HttpMethod.POST, "/Boards/**").hasRole("ADMIN") 57 | .anyRequest().permitAll() 58 | .and().cors().configurationSource(source) 59 | .and().csrf().disable(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/controller/BoardRestController.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.controller; 2 | 3 | import com.community.rest.domain.Board; 4 | import com.community.rest.repository.BoardRepository; 5 | 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.data.web.PageableDefault; 9 | import org.springframework.hateoas.PagedResources; 10 | import org.springframework.hateoas.PagedResources.PageMetadata; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.http.MediaType; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.DeleteMapping; 15 | import org.springframework.web.bind.annotation.GetMapping; 16 | import org.springframework.web.bind.annotation.PathVariable; 17 | import org.springframework.web.bind.annotation.PostMapping; 18 | import org.springframework.web.bind.annotation.PutMapping; 19 | import org.springframework.web.bind.annotation.RequestBody; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RestController; 22 | 23 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; 24 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; 25 | 26 | @RestController 27 | @RequestMapping("/api/boards") 28 | public class BoardRestController { 29 | 30 | private BoardRepository boardRepository; 31 | 32 | public BoardRestController(BoardRepository boardRepository) { 33 | this.boardRepository = boardRepository; 34 | } 35 | 36 | @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) 37 | public ResponseEntity getBoards(@PageableDefault Pageable pageable) { 38 | Page boards = boardRepository.findAll(pageable); 39 | PageMetadata pageMetadata = new PageMetadata(pageable.getPageSize(), boards.getNumber(), boards.getTotalElements()); 40 | PagedResources resources = new PagedResources<>(boards.getContent(), pageMetadata); 41 | resources.add(linkTo(methodOn(BoardRestController.class).getBoards(pageable)).withSelfRel()); 42 | return ResponseEntity.ok(resources); 43 | } 44 | 45 | @PostMapping 46 | public ResponseEntity postBoard(@RequestBody Board board) { 47 | //valid 체크 48 | board.setCreatedDateNow(); 49 | boardRepository.save(board); 50 | return new ResponseEntity<>("{}", HttpStatus.CREATED); 51 | } 52 | 53 | @PutMapping("/{idx}") 54 | public ResponseEntity putBoard(@PathVariable("idx")Long idx, @RequestBody Board board) { 55 | //valid 체크 56 | Board persistBoard = boardRepository.getOne(idx) ; 57 | persistBoard.update(board); 58 | boardRepository.save(persistBoard); 59 | return new ResponseEntity<>("{}", HttpStatus.OK); 60 | } 61 | 62 | @DeleteMapping("/{idx}") 63 | public ResponseEntity deleteBoard(@PathVariable("idx")Long idx) { 64 | //valid 체크 65 | boardRepository.deleteById(idx); 66 | return new ResponseEntity<>("{}", HttpStatus.OK); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/domain/Board.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain; 2 | 3 | 4 | import com.community.rest.domain.enums.BoardType; 5 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 6 | 7 | import java.io.Serializable; 8 | import java.time.LocalDateTime; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.EnumType; 13 | import javax.persistence.Enumerated; 14 | import javax.persistence.FetchType; 15 | import javax.persistence.GeneratedValue; 16 | import javax.persistence.Id; 17 | import javax.persistence.OneToOne; 18 | import javax.persistence.Table; 19 | 20 | import lombok.Builder; 21 | import lombok.Getter; 22 | import lombok.NoArgsConstructor; 23 | 24 | /** 25 | * Created by KimYJ on 2017-07-12. 26 | */ 27 | @Getter 28 | @NoArgsConstructor 29 | @Entity 30 | @Table 31 | public class Board implements Serializable { 32 | 33 | @Id 34 | @Column 35 | @GeneratedValue 36 | private Long idx; 37 | 38 | @Column 39 | private String title; 40 | 41 | @Column 42 | private String subTitle; 43 | 44 | @Column 45 | private String content; 46 | 47 | @Column 48 | @Enumerated(EnumType.STRING) 49 | private BoardType boardType; 50 | 51 | @Column 52 | private LocalDateTime createdDate; 53 | 54 | @Column 55 | private LocalDateTime updatedDate; 56 | 57 | @OneToOne 58 | private User user; 59 | 60 | @Builder 61 | public Board(String title, String subTitle, String content, BoardType boardType, LocalDateTime createdDate, LocalDateTime updatedDate, User user) { 62 | this.title = title; 63 | this.subTitle = subTitle; 64 | this.content = content; 65 | this.boardType = boardType; 66 | this.createdDate = createdDate; 67 | this.updatedDate = updatedDate; 68 | this.user = user; 69 | } 70 | 71 | public void setCreatedDateNow() { 72 | this.createdDate = LocalDateTime.now(); 73 | } 74 | 75 | public void update(Board board) { 76 | this.title = board.getTitle(); 77 | this.subTitle = board.getSubTitle(); 78 | this.content = board.getContent(); 79 | this.boardType = board.getBoardType(); 80 | this.updatedDate = LocalDateTime.now(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain; 2 | 3 | 4 | import com.community.rest.domain.enums.SocialType; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.EnumType; 12 | import javax.persistence.Enumerated; 13 | import javax.persistence.GeneratedValue; 14 | import javax.persistence.Id; 15 | import javax.persistence.Table; 16 | 17 | import lombok.Builder; 18 | import lombok.Getter; 19 | import lombok.NoArgsConstructor; 20 | 21 | /** 22 | * Created by KimYJ on 2017-07-12. 23 | */ 24 | @Getter 25 | @NoArgsConstructor 26 | @Entity 27 | @Table 28 | public class User implements Serializable { 29 | 30 | @Id 31 | @Column 32 | @GeneratedValue 33 | private Long idx; 34 | 35 | @Column 36 | private String name; 37 | 38 | @Column 39 | private String password; 40 | 41 | @Column 42 | private String email; 43 | 44 | @Column 45 | private String pincipal; 46 | 47 | @Column 48 | @Enumerated(EnumType.STRING) 49 | private SocialType socialType; 50 | 51 | @Column 52 | private LocalDateTime createdDate; 53 | 54 | @Column 55 | private LocalDateTime updatedDate; 56 | 57 | @Builder 58 | public User(String name, String password, String email, String pincipal, SocialType socialType, LocalDateTime createdDate, LocalDateTime updatedDate) { 59 | this.name = name; 60 | this.password = password; 61 | this.email = email; 62 | this.pincipal = pincipal; 63 | this.socialType = socialType; 64 | this.createdDate = createdDate; 65 | this.updatedDate = updatedDate; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/domain/enums/BoardType.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain.enums; 2 | 3 | /** 4 | * Created by KimYJ on 2017-07-12. 5 | */ 6 | public enum BoardType { 7 | notice("공지사항"), 8 | free("자유게시판"); 9 | 10 | private String value; 11 | 12 | BoardType(String value) { 13 | this.value = value; 14 | } 15 | 16 | public String getValue() { 17 | return this.value; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/domain/enums/SocialType.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.domain.enums; 2 | 3 | public enum SocialType { 4 | FACEBOOK("facebook"), 5 | GOOGLE("google"), 6 | KAKAO("kakao"); 7 | 8 | private final String ROLE_PREFIX = "ROLE_"; 9 | private String name; 10 | 11 | SocialType(String name) { 12 | this.name = name; 13 | } 14 | 15 | public String getRoleType() { return ROLE_PREFIX + name.toUpperCase(); } 16 | 17 | public String getValue() { return name; } 18 | 19 | public boolean isEquals(String authority) { 20 | return this.getRoleType().equals(authority); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/repository/BoardRepository.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.repository; 2 | 3 | import com.community.rest.domain.Board; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface BoardRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /rest-web/src/main/java/com/community/rest/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.community.rest.repository; 2 | 3 | import com.community.rest.domain.User; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface UserRepository extends JpaRepository { 10 | } 11 | -------------------------------------------------------------------------------- /rest-web/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:mysql://172.16.135.15:3306/autoconfiguration 4 | username: mns 5 | password: dltmxmdlsxjspt 6 | driver-class-name: com.mysql.jdbc.Driver 7 | # jackson: 8 | # serialization: 9 | # fail-on-empty-beans: false #빈값은 직렬화하지 않음 10 | server: 11 | port: 8081 -------------------------------------------------------------------------------- /rest-web/src/test/java/com/community/rest/RestWebApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.community.rest; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RestWebApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'boot-rest' 2 | 3 | include 'data-rest' 4 | include 'rest-web' 5 | 6 | --------------------------------------------------------------------------------