Skip to content

Commit

Permalink
[게시판 회원 기능] 지노 미션 제출합니다. (woowacourse#79)
Browse files Browse the repository at this point in the history
* feat: thymeleaf 추가, html 파일 templates 디렉토리로 이동

* feat: Test 주석추가

* feat: ArticleController 추가

* feat: Article 클래스 추가

* [DOCS] Add README.md

* [ADD] Add dependencies

* [ADD] Add properties

* [MOVE] Move views to templates directory

* [ADD] Add properties

* [FEATURE] Implement redirection to article writing page

* [FEATURE] Implement methods for read and create article

* [FEATURE] Implement methods for read article edit page

* [FEATURE] Implement methods for update article

* [FEATURE] implement methods for delete article

* feat: 게시글 수정, 삭제 기능 구현

* [FEATURE] Implement methods for read all articles

* [FEATURE] Apply template to article page

* refactor: 코드 리팩토링

* refactor: 함수명 수정

* refactor: Controller 메서드명 수정

* [REFACTOR] adjust put method to article edit page

- 메소드 타입에 따른 해당 메소드 뷰 적용

* [REFACTOR] replace response from rendering to redirection

* [ADD] Update css and html for bug fix

* [FEATURE] Apply delete specific article

* [REFACTOR] management role from Article to ArticleRepository

* [REFACTOR] update for redirection tests

* [REFACTOR] remove duplicated html

* [REMOVE] unnecessary class and test

* [FEATURE] Create and apply error pages

* [REFACTOR] Move and rename Main controller

* [REFACTOR] Modify controller name

* [REFACTOR] Modify new article id from 0 to 1

* [REFACTOR] Modify repository method name to remove correlation with db

* [REFACTOR] Modify int to AtomicInteger

* [REFACTOR] Apply code alignment

* [REFACTOR] Modify field dependency injection to constructor dependency injection

* [REFACTOR] Modify constructor

세터 제거 및 생성자 private으로 변경.

* refactor: 코드 리팩토링

* refactor: 매서드 위치 수정

* refactor: 리뷰 반영

* refactor: 리뷰 반영 : setter 메서드명 번경

* [REFACTOR] Remove of() static factory method

* [FIX] add id attribute

* [REFACTOR] Apply constant at auto-increment value

* refactor: 리뷰 반영, ArticleRepository.class update 메서드 삭제

* refactor: 리뷰 반영, ArticleRepository.class 수정에 따른 테스트 코드 삭제

* [REFACTOR] Apply code alignment

* refactor: 리뷰 반영, controller ModelAnvView 메서드 내부에서 수정

* refactor: 테스트 코드 수정

* [REFACTOR] Remove console logs

* [REFACTOR] Remove modifyArticle method

* [REFACTOR] Modify Setter name

* [REFACTOR] Modify save method

modify method가 필요없도록 수정

* [REFACTOR] Modify id from int to Long

* [FIX] Fix typing error

* [REFACTOR] Change update request

findArticle(id) 후 해당 Article을 수정하도록 변경

* refactor 피드백 반영

* refactor 피드백 반영

* [ADD] Add db for test

프로덕트 코드에 MySQL, 테스트 코드에 H2 적용

* [FEATURE] Apply JPA

Repository에 CrudRepository 상속받도록 적용.

* [ADD] Add dto for Article Domain Model

* [FEATURE] Implements create and read user

* [FEATURE] Implements login

* [FEATURE] Implement modify user

* [FEATURE] Implement delete user

* [FEATURE] Add logback dependency

* [FEATURE] Implement interceptor for session

* [FEATURE] Implement logout

* [FEATURE] Implement exception handler

* [FEATURE] Implement login dto and exception

* [FEATURE] Test Controller

* [REFACTOR] Move WebMvcConfig Class to config package

* [ADD] Add User Entity Tests

* [ADD] Add Article Service

* [REFACTOR] Remove unnecessary classes

* [REFACTOR] Remove unnecessary classes

* [ADD] Add static factory method at UserDto

* [ADD] Add tests for UserService

* [REFACTOR] remove duplicates

* [REFACTOR] remove unnecessary exceptions

* [ADD] Add error message for session interceptor

* Revert "[게시글 생성/조회/수정/삭제] 지노 미션 제출합니다. (woowacourse#45)"

This reverts commit 72e0dc0.

* refactor

* refactor 피드백 반영

* refactor 피드백 반영
  • Loading branch information
qpwoeiru789 authored and hyojaekim committed Jul 30, 2019
1 parent e4de223 commit a9efec4
Show file tree
Hide file tree
Showing 49 changed files with 1,490 additions and 425 deletions.
Binary file added .DS_Store
Binary file not shown.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## 나만의 블로그 서비스 (1주차)

### 기능 요구사항
- 게시글 생성
- 게시글 작성 페이지 이동
- 메인페이지(index.html)에서 게시글 생성 버튼을 누르기
- GET /writing 으로 요청
- 작성 페이지(article-edit.html)로 이동
- 게시글 작성
- POST /articles 으로 요청
- 게시글 생성 시 게시글은 ArticleRepository의 List<Article> articles에 저장한다.
- 게시글 페이지(article.html)로 이동
- 게시글 목록 조회
- 메인 페이지 이동
- GET / 으로 요청으로 이동 시 메인 페이지에 게시글 목록이 노출
- 게시글 조회
- 게시글 페이지 이동
- 메인페이지(index.html)에서 게시글을 클릭 시 게시글 페이지(article.html)으로 이동
- GET /articles/{articleId} 으로 요청

- 게시글 수정
- 게시글 수정 페이지 이동
- 게시글 페이지(article.html)에서 수정 버튼 누르기
- GET /articles/{articleId}/edit 으로 요청
- 게시글 수정 페이지(article-edit.html)로 이동
- 게시글 수정
- PUT /articles/{articleId} 으로 요청
- 게시글 페이지(article.html)로 이동
- 게시글 삭제
- 게시글 페이지(article.html)에서 삭제 버튼 누르기
- DELETE /articles/{articleId} 으로 요청
- 게시글 목록 조회 페이지(index.html)로 이동


### 제약조건
- HTML 중복제거
- 정적 파일 수정 시 재시작 하지 않고 변경사항 반영하기
- class 파일 수정 시 자동으로 재시작 하기
19 changes: 17 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,37 @@ plugins {
}

apply plugin: 'io.spring.dependency-management'
apply plugin: 'org.springframework.boot'

group = 'techcourse'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
targetCompatibility = 1.8

bootJar {
baseName = 'gs-accessing-data-mysql'
version = '0.1.0'
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2'
implementation 'mysql:mysql-connector-java'

runtimeOnly 'net.rakugakibox.spring.boot:logback-access-spring-boot-starter:2.7.1'

testImplementation 'org.junit.jupiter:junit-jupiter-api'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'junit'
}
testImplementation 'org.springframework.boot:spring-boot-starter-webflux'
}
testImplementation("org.springframework.boot:spring-boot-devtools")

}
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Wed Jul 10 14:33:33 KST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/main/.DS_Store
Binary file not shown.
1 change: 0 additions & 1 deletion src/main/java/techcourse/myblog/MyblogApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

@SpringBootApplication
public class MyblogApplication {

public static void main(String[] args) {
SpringApplication.run(MyblogApplication.class, args);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package techcourse.myblog.application.converter;

import techcourse.myblog.application.dto.ArticleDto;
import techcourse.myblog.domain.Article;

public class ArticleConverter extends Converter<ArticleDto, Article> {

private static class ArticleConverterHolder {
private static final ArticleConverter INSTANCE = new ArticleConverter();
}

public static ArticleConverter getInstance() {
return ArticleConverter.ArticleConverterHolder.INSTANCE;
}

private ArticleConverter() {
super(articleDto -> new Article(
articleDto.getTitle(),
articleDto.getCoverUrl(),
articleDto.getContents()
),
article -> new ArticleDto(
article.getId(),
article.getTitle(),
article.getCoverUrl(),
article.getContents())
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package techcourse.myblog.application.converter;

import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Converter<T, U> {
private final Function<T, U> fromDto;
private final Function<U, T> fromEntity;

public Converter(final Function<T, U> fromDto, final Function<U, T> fromEntity) {
this.fromDto = fromDto;
this.fromEntity = fromEntity;
}

public final U convertFromDto(final T dto) {
return fromDto.apply(dto);
}

public final T convertFromEntity(final U entity) {
return fromEntity.apply(entity);
}

public final List<U> createFromDtos(final Collection<T> dtos) {
return dtos.stream()
.map(this::convertFromDto)
.collect(Collectors.toList());
}


public final List<T> createFromEntities(final Collection<U> entities) {
return entities.stream()
.map(this::convertFromEntity)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package techcourse.myblog.application.converter;

import techcourse.myblog.application.dto.UserDto;
import techcourse.myblog.domain.User;

public class UserConverter extends Converter<UserDto, User> {

private static class UserConverterHolder {
private static final UserConverter INSTANCE = new UserConverter();
}

public static UserConverter getInstance() {
return UserConverterHolder.INSTANCE;
}

private UserConverter() {
super(userDto -> new User(
userDto.getEmail(),
userDto.getName(),
userDto.getPassword()),
user -> new UserDto(
user.getEmail(),
user.getName(),
user.getPassword()
)
);
}
}
56 changes: 56 additions & 0 deletions src/main/java/techcourse/myblog/application/dto/ArticleDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package techcourse.myblog.application.dto;

import techcourse.myblog.domain.Article;

public class ArticleDto {
private Long id;
private String title;
private String coverUrl;
private String contents;

public ArticleDto(Long id, String title, String coverUrl, String contents) {
this.id = id;
this.title = title;
this.coverUrl = coverUrl;
this.contents = contents;
}

public static ArticleDto of(Article article) {
return new ArticleDto(article.getId(),
article.getTitle(),
article.getCoverUrl(),
article.getContents());
}

public String getTitle() {
return title;
}

public String getCoverUrl() {
return coverUrl;
}

public String getContents() {
return contents;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public void setTitle(String title) {
this.title = title;
}

public void setCoverUrl(String coverUrl) {
this.coverUrl = coverUrl;
}

public void setContents(String contents) {
this.contents = contents;
}
}
40 changes: 40 additions & 0 deletions src/main/java/techcourse/myblog/application/dto/LoginDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package techcourse.myblog.application.dto;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

public class LoginDto {
@NotBlank(message = "이메일을 작성해주세요.")
@Email(message = "메일의 양식을 지켜주세요.")
private String email;

@NotBlank(message = "비밀번호를 작성해주세요.")
@Pattern(regexp = "^([a-zA-Z0-9!@#$%^&*]{8,})$", message = "8자리 이상의 글자, 숫자, 특수문자를 입력해야합니다.")
private String password;

public LoginDto(String email, String password){
this.email = email;
this.password = password;
}

public static LoginDto of(UserDto userDto){
return new LoginDto(userDto.getEmail(), userDto.getPassword());
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}
68 changes: 68 additions & 0 deletions src/main/java/techcourse/myblog/application/dto/UserDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package techcourse.myblog.application.dto;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.util.Objects;

public class UserDto {
@NotBlank(message = "이메일을 작성해주세요.")
@Email(message = "메일의 양식을 지켜주세요.")
private String email;

@NotBlank(message = "이름을 작성해주세요.")
@Pattern(regexp = "^([A-Za-z가-힣]{2,10})$", message = "2~10자리 숫자, 글자만 입력가능합니다.")
private String name;

@NotBlank(message = "비밀번호를 작성해주세요.")
@Pattern(regexp = "^([a-zA-Z0-9!@#$%^&*]{8,})$", message = "8자리 이상의 글자, 숫자, 특수문자를 입력해야합니다.")
private String password;

public UserDto(String email, String name, String password) {
this.email = email;
this.name = name;
this.password = password;
}

public UserDto() {
}

public void setEmail(String email) {
this.email = email;
}

public void setName(String name) {
this.name = name;
}

public void setPassword(String password) {
this.password = password;
}

public String getEmail() {
return email;
}

public String getName() {
return name;
}

public String getPassword() {
return password;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserDto userDto = (UserDto) o;
return email.equals(userDto.email) &&
name.equals(userDto.name) &&
password.equals(userDto.password);
}

@Override
public int hashCode() {
return Objects.hash(email, name, password);
}
}
Loading

0 comments on commit a9efec4

Please sign in to comment.