-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: ehtjsv2 <[email protected]> Co-authored-by: jimi567 <[email protected]> Co-authored-by: 이충렬(트레) <[email protected]>
- Loading branch information
1 parent
52c4eab
commit 621cc1f
Showing
39 changed files
with
1,065 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,55 @@ | ||
plugins { | ||
id 'java' | ||
id 'org.springframework.boot' version '3.3.1' | ||
id 'io.spring.dependency-management' version '1.1.5' | ||
id 'org.asciidoctor.jvm.convert' version '3.3.2' | ||
id 'java' | ||
id 'org.springframework.boot' version '3.3.1' | ||
id 'io.spring.dependency-management' version '1.1.5' | ||
id 'org.asciidoctor.jvm.convert' version '3.3.2' | ||
} | ||
|
||
group = 'com.woowacourse' | ||
version = '0.0.1-SNAPSHOT' | ||
|
||
java { | ||
toolchain { | ||
languageVersion = JavaLanguageVersion.of(17) | ||
} | ||
toolchain { | ||
languageVersion = JavaLanguageVersion.of(17) | ||
} | ||
} | ||
|
||
configurations { | ||
compileOnly { | ||
extendsFrom annotationProcessor | ||
} | ||
compileOnly { | ||
extendsFrom annotationProcessor | ||
} | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
mavenCentral() | ||
} | ||
|
||
ext { | ||
set('snippetsDir', file("build/generated-snippets")) | ||
set('snippetsDir', file("build/generated-snippets")) | ||
} | ||
|
||
dependencies { | ||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
implementation 'org.springframework.boot:spring-boot-starter-validation' | ||
|
||
compileOnly 'org.projectlombok:lombok' | ||
runtimeOnly 'com.h2database:h2' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
compileOnly 'org.projectlombok:lombok' | ||
runtimeOnly 'com.h2database:h2' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
|
||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' | ||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' | ||
testImplementation 'io.rest-assured:rest-assured:5.4.0' | ||
|
||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||
} | ||
|
||
tasks.named('test') { | ||
outputs.dir snippetsDir | ||
useJUnitPlatform() | ||
outputs.dir snippetsDir | ||
useJUnitPlatform() | ||
} | ||
|
||
tasks.named('asciidoctor') { | ||
inputs.dir snippetsDir | ||
dependsOn test | ||
inputs.dir snippetsDir | ||
dependsOn test | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
backend/src/main/java/com/woowacourse/friendogly/GlobalExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.woowacourse.friendogly; | ||
|
||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.http.converter.HttpMessageNotReadableException; | ||
import org.springframework.web.HttpRequestMethodNotSupportedException; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
import org.springframework.web.servlet.resource.NoResourceFoundException; | ||
|
||
@RestControllerAdvice | ||
public class GlobalExceptionHandler { | ||
|
||
@ExceptionHandler(IllegalArgumentException.class) | ||
public ResponseEntity<String> handle(RuntimeException exception) { | ||
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
@ExceptionHandler(HttpMessageNotReadableException.class) | ||
public ResponseEntity<String> handle(HttpMessageNotReadableException exception) { | ||
return new ResponseEntity<>("읽을 수 없는 HTTP 메세지입니다.", HttpStatus.BAD_REQUEST); | ||
} | ||
|
||
@ExceptionHandler(HttpRequestMethodNotSupportedException.class) | ||
public ResponseEntity<String> handle(HttpRequestMethodNotSupportedException exception) { | ||
return new ResponseEntity<>("지원하지 않는 HTTP 메서드입니다.", HttpStatus.METHOD_NOT_ALLOWED); | ||
} | ||
|
||
@ExceptionHandler(NoResourceFoundException.class) | ||
public ResponseEntity<String> handle(NoResourceFoundException exception) { | ||
return new ResponseEntity<>("존재하지 않는 요청 경로입니다.", HttpStatus.NOT_FOUND); | ||
} | ||
|
||
@ExceptionHandler(Exception.class) | ||
public ResponseEntity<String> handle(Exception exception) { | ||
return new ResponseEntity<>("예기치 못한 예외가 발생하였습니다. 다시 실행해주세요.", HttpStatus.INTERNAL_SERVER_ERROR); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
...nd/src/main/java/com/woowacourse/friendogly/footprint/controller/FootprintController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.woowacourse.friendogly.footprint.controller; | ||
|
||
import com.woowacourse.friendogly.footprint.dto.request.FindNearFootprintRequest; | ||
import com.woowacourse.friendogly.footprint.dto.request.SaveFootprintRequest; | ||
import com.woowacourse.friendogly.footprint.dto.response.FindNearFootprintResponse; | ||
import com.woowacourse.friendogly.footprint.service.FootprintCommandService; | ||
import com.woowacourse.friendogly.footprint.service.FootprintQueryService; | ||
import java.net.URI; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/footprints") | ||
public class FootprintController { | ||
|
||
private final FootprintCommandService footprintCommandService; | ||
private final FootprintQueryService footprintQueryService; | ||
|
||
@PostMapping | ||
public ResponseEntity<Void> save(@RequestBody SaveFootprintRequest request) { | ||
Long id = footprintCommandService.save(request); | ||
return ResponseEntity.created(URI.create("/footprints/" + id)) | ||
.build(); | ||
} | ||
|
||
@GetMapping("/near") | ||
public List<FindNearFootprintResponse> findNear( | ||
@RequestParam double lat, | ||
@RequestParam double lng | ||
) { | ||
return footprintQueryService.findNear(new FindNearFootprintRequest(lat, lng)); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
backend/src/main/java/com/woowacourse/friendogly/footprint/domain/Footprint.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.woowacourse.friendogly.footprint.domain; | ||
|
||
import com.woowacourse.friendogly.member.domain.Member; | ||
import jakarta.persistence.Embedded; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.GeneratedValue; | ||
import jakarta.persistence.GenerationType; | ||
import jakarta.persistence.Id; | ||
import jakarta.persistence.ManyToOne; | ||
import java.time.LocalDateTime; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Entity | ||
@Getter | ||
@NoArgsConstructor | ||
public class Footprint { | ||
|
||
@Id | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private Long id; | ||
|
||
@ManyToOne | ||
private Member member; | ||
|
||
@Embedded | ||
private Location location; | ||
|
||
private LocalDateTime createdAt; | ||
|
||
private boolean isDeleted; | ||
|
||
@Builder | ||
public Footprint(Member member, Location location) { | ||
this.member = member; | ||
this.location = location; | ||
this.createdAt = LocalDateTime.now(); | ||
this.isDeleted = false; | ||
} | ||
|
||
public boolean isNear(Location location) { | ||
return this.location.isNear(location); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
backend/src/main/java/com/woowacourse/friendogly/footprint/domain/Location.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.woowacourse.friendogly.footprint.domain; | ||
|
||
import jakarta.persistence.Embeddable; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Embeddable | ||
@Getter | ||
@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
@AllArgsConstructor | ||
public class Location { | ||
|
||
private static final int BOUNDARY_RADIUS_METER = 1000; | ||
|
||
private double latitude; | ||
private double longitude; | ||
|
||
public boolean isNear(Location other) { | ||
return distance(this.latitude, this.longitude, other.latitude, other.longitude) <= BOUNDARY_RADIUS_METER; | ||
} | ||
|
||
private double distance(double lat1, double lon1, double lat2, double lon2) { | ||
double theta = lon1 - lon2; | ||
double dist = Math.sin(degToRad(lat1)) * Math.sin(degToRad(lat2)) + | ||
Math.cos(degToRad(lat1)) * Math.cos(degToRad(lat2)) * Math.cos(degToRad(theta)); | ||
|
||
dist = Math.acos(dist); | ||
dist = radToDeg(dist); | ||
dist = dist * 60 * 1.1515 * 1609.344; | ||
|
||
return Math.abs(dist); | ||
} | ||
|
||
private double degToRad(double deg) { | ||
return (deg * Math.PI / 180.0); | ||
} | ||
|
||
private double radToDeg(double rad) { | ||
return (rad * 180 / Math.PI); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
.../main/java/com/woowacourse/friendogly/footprint/dto/request/FindNearFootprintRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.woowacourse.friendogly.footprint.dto.request; | ||
|
||
public record FindNearFootprintRequest(double latitude, double longitude) { | ||
|
||
} |
5 changes: 5 additions & 0 deletions
5
.../src/main/java/com/woowacourse/friendogly/footprint/dto/request/SaveFootprintRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.woowacourse.friendogly.footprint.dto.request; | ||
|
||
public record SaveFootprintRequest(Long memberId, double latitude, double longitude) { | ||
|
||
} |
21 changes: 21 additions & 0 deletions
21
...ain/java/com/woowacourse/friendogly/footprint/dto/response/FindNearFootprintResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.woowacourse.friendogly.footprint.dto.response; | ||
|
||
import com.woowacourse.friendogly.footprint.domain.Footprint; | ||
import java.time.LocalDateTime; | ||
|
||
public record FindNearFootprintResponse( | ||
Long memberId, | ||
double latitude, | ||
double longitude, | ||
LocalDateTime createdAt | ||
) { | ||
|
||
public static FindNearFootprintResponse from(Footprint footprint) { | ||
return new FindNearFootprintResponse( | ||
footprint.getMember().getId(), | ||
footprint.getLocation().getLatitude(), | ||
footprint.getLocation().getLongitude(), | ||
footprint.getCreatedAt() | ||
); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
...nd/src/main/java/com/woowacourse/friendogly/footprint/repository/FootprintRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.woowacourse.friendogly.footprint.repository; | ||
|
||
import com.woowacourse.friendogly.footprint.domain.Footprint; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface FootprintRepository extends JpaRepository<Footprint, Long> { | ||
|
||
List<Footprint> findByCreatedAtAfter(LocalDateTime since); | ||
} |
34 changes: 34 additions & 0 deletions
34
...d/src/main/java/com/woowacourse/friendogly/footprint/service/FootprintCommandService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.woowacourse.friendogly.footprint.service; | ||
|
||
import com.woowacourse.friendogly.footprint.domain.Footprint; | ||
import com.woowacourse.friendogly.footprint.domain.Location; | ||
import com.woowacourse.friendogly.footprint.dto.request.SaveFootprintRequest; | ||
import com.woowacourse.friendogly.footprint.repository.FootprintRepository; | ||
import com.woowacourse.friendogly.member.domain.Member; | ||
import com.woowacourse.friendogly.member.repository.MemberRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Transactional | ||
@RequiredArgsConstructor | ||
public class FootprintCommandService { | ||
|
||
private final FootprintRepository footprintRepository; | ||
private final MemberRepository memberRepository; | ||
|
||
public Long save(SaveFootprintRequest request) { | ||
Member member = memberRepository.findById(request.memberId()) | ||
.orElseThrow(() -> new IllegalArgumentException("멤버 없음")); | ||
|
||
Footprint footprint = footprintRepository.save( | ||
Footprint.builder() | ||
.member(member) | ||
.location(new Location(request.latitude(), request.longitude())) | ||
.build() | ||
); | ||
|
||
return footprint.getId(); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
...end/src/main/java/com/woowacourse/friendogly/footprint/service/FootprintQueryService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.woowacourse.friendogly.footprint.service; | ||
|
||
import com.woowacourse.friendogly.footprint.domain.Footprint; | ||
import com.woowacourse.friendogly.footprint.domain.Location; | ||
import com.woowacourse.friendogly.footprint.dto.request.FindNearFootprintRequest; | ||
import com.woowacourse.friendogly.footprint.dto.response.FindNearFootprintResponse; | ||
import com.woowacourse.friendogly.footprint.repository.FootprintRepository; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Transactional(readOnly = true) | ||
@RequiredArgsConstructor | ||
public class FootprintQueryService { | ||
|
||
private static final int HOURS_AGO = 24; | ||
|
||
private final FootprintRepository footprintRepository; | ||
|
||
public List<FindNearFootprintResponse> findNear(FindNearFootprintRequest request) { | ||
LocalDateTime since = LocalDateTime.now().minusHours(HOURS_AGO); | ||
List<Footprint> recentFootprints = footprintRepository.findByCreatedAtAfter(since); | ||
|
||
Location currentLocation = new Location(request.latitude(), request.longitude()); | ||
|
||
return recentFootprints.stream() | ||
.filter(footprint -> footprint.isNear(currentLocation)) | ||
.map(FindNearFootprintResponse::from) | ||
.toList(); | ||
} | ||
} |
Oops, something went wrong.