From 7cb753ed2e3c0e8d067b03a2b7607fa164283b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?= =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= Date: Tue, 18 Apr 2023 00:04:42 +0400 Subject: [PATCH] Lab5: Completed first stage(added @RequestBody and some other things) --- build.gradle | 6 +++ frontend/src/App.vue | 2 +- frontend/src/components/Customers.vue | 22 ++++++---- frontend/src/components/Posts.vue | 40 ++++++++++++++----- .../java/np/something/DTO/CommentDto.java | 37 +++++++++++++---- .../java/np/something/DTO/CustomerDto.java | 19 ++++++--- src/main/java/np/something/DTO/PostDto.java | 22 ++++++---- .../java/np/something/WebConfiguration.java | 2 + .../controllers/CommentController.java | 16 +++++--- .../controllers/CustomerController.java | 12 +++--- .../something/controllers/PostController.java | 20 ++++------ .../util/error/AdviceController.java | 3 +- 12 files changed, 139 insertions(+), 62 deletions(-) diff --git a/build.gradle b/build.gradle index 57bd44b..34eb38a 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,12 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'com.h2database:h2:2.1.210' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-devtools' + implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' + implementation 'org.webjars:bootstrap:5.1.3' + implementation 'org.webjars:jquery:3.6.0' + implementation 'org.webjars:font-awesome:6.1.0' implementation group: 'org.springdoc', name: 'springdoc-openapi-ui', version: '1.6.5' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'org.hibernate.validator:hibernate-validator' diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 6845d17..1714cda 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -30,7 +30,7 @@ export default { }, async beforeMount() { setInterval(async () => { - const response = await axios.get('http://localhost:8080/customer'); + const response = await axios.get('http://localhost:8080/api/customer'); this.customers = []; response.data.forEach(element => { this.customers.push(element); diff --git a/frontend/src/components/Customers.vue b/frontend/src/components/Customers.vue index a50b20d..57a01e3 100644 --- a/frontend/src/components/Customers.vue +++ b/frontend/src/components/Customers.vue @@ -109,27 +109,35 @@ export default { }, methods: { async createUser(){ - const response = await axios.post('http://localhost:8080/customer?username=' + this.usernameModal + '&password=' + this.passwordModal); + let customer = { + username: this.usernameModal, + password: this.passwordModal + }; + const response = await axios.post('http://localhost:8080/api/customer', customer); this.refreshList(); }, async deleteUser(id) { - const response = await axios.delete('http://localhost:8080/customer/' + id); + const response = await axios.delete('http://localhost:8080/api/customer/' + id); this.refreshList(); }, async editUser() { - const response = await axios.put('http://localhost:8080/customer/' + this.selectedCustomer['id'] + '?username=' + this.usernameModal + '&password=' + this.passwordModal); + let customer = { + username: this.usernameModal, + password: this.passwordModal + }; + const response = await axios.put('http://localhost:8080/api/customer/' + this.selectedCustomer['id'], customer); this.refreshList(); }, async refreshList() { this.customers = []; if (this.$route.params.id === "") { - const response = await axios.get('http://localhost:8080/customer'); + const response = await axios.get('http://localhost:8080/api/customer'); response.data.forEach(element => { this.customers.push(element); console.log(element); }); } else { - const response = await axios.get('http://localhost:8080/customer/' + this.$route.params.id); + const response = await axios.get('http://localhost:8080/api/customer/' + this.$route.params.id); this.customers.push(response.data) } }, @@ -139,13 +147,13 @@ export default { this.currentCustomerId = history.state; setInterval(async () => this.currentCustomerId = history.state, 50) if (this.$route.params.id === "") { - const response = await axios.get('http://localhost:8080/customer'); + const response = await axios.get('http://localhost:8080/api/customer'); response.data.forEach(element => { this.customers.push(element); console.log(element); }); } else { - const response = await axios.get('http://localhost:8080/customer/' + this.$route.params.id); + const response = await axios.get('http://localhost:8080/api/customer/' + this.$route.params.id); this.customers.push(response.data) } diff --git a/frontend/src/components/Posts.vue b/frontend/src/components/Posts.vue index 4435368..5e10131 100644 --- a/frontend/src/components/Posts.vue +++ b/frontend/src/components/Posts.vue @@ -161,42 +161,62 @@ export default { async createComment() { const content = document.getElementById("post-comment-" + this.selectedPostId).value - await axios.post('http://localhost:8080/comment?text=' + content + '&ownerId=' + this.currentCustomerId + '&postId=' + this.selectedPostId); + let comment = { + "content": content, + customerId: this.currentCustomerId, + postId: this.selectedPostId + }; + await axios.post('http://localhost:8080/api/comment', comment); document.getElementById("post-comment-" + this.selectedPostId).value = '' this.refreshList(); }, async deleteComment(commentId) { - await axios.delete('http://localhost:8080/comment/' + commentId); + await axios.delete('http://localhost:8080/api/comment/' + commentId); this.refreshList(); }, async editComment(){ - await axios.put('http://localhost:8080/comment/' + this.selectedCommentId + '?text=' + this.contentModal); + let comment = { + content: this.contentModal, + customerId: this.currentCustomerId, + postId: 0 + }; + await axios.put('http://localhost:8080/api/comment/' + this.selectedCommentId, comment); this.refreshList(); }, async createPost() { - const response = await axios.post('http://localhost:8080/post?title=' + this.titleModal + '&content=' + this.postContentModal + '&authorId=' + this.currentCustomerId); + let post = { + "content": this.postContentModal, + title: this.titleModal, + customerId: this.currentCustomerId + }; + const response = await axios.post('http://localhost:8080/api/post', post); this.titleModal = '' this.postContentModal = '' this.refreshList(); }, async deletePost(postId) { - const response = await axios.delete('http://localhost:8080/post/' + postId); + const response = await axios.delete('http://localhost:8080/api/post/' + postId); this.refreshList(); }, async editPost(){ - const response = await axios.put('http://localhost:8080/post/' + this.selectedPostId + '?title=' + this.titleModal + '&content=' + this.postContentModal); + let post = { + "content": this.postContentModal, + title: this.titleModal, + customerId: this.currentCustomerId + }; + const response = await axios.put('http://localhost:8080/api/post/' + this.selectedPostId, post); this.refreshList(); }, async refreshList(){ this.customers = []; this.posts = []; - const responseCustomer = await axios.get('http://localhost:8080/customer'); + const responseCustomer = await axios.get('http://localhost:8080/api/customer'); responseCustomer.data.forEach(element => { this.customers.push(element); console.log(element); }); - const responsePost = await axios.get('http://localhost:8080/post'); + const responsePost = await axios.get('http://localhost:8080/api/post'); responsePost.data.forEach(element => { this.posts.splice(0, 0, element); console.log(element); @@ -206,7 +226,7 @@ export default { async beforeMount() { this.currentCustomerId = history.state; setInterval(async () => this.currentCustomerId = history.state, 50) - const responseCustomer = await axios.get('http://localhost:8080/customer'); + const responseCustomer = await axios.get('http://localhost:8080/api/customer'); responseCustomer.data.forEach(element => { this.customers.push(element); if (element['id'] == this.currentCustomerId) { @@ -214,7 +234,7 @@ export default { } console.log(element); }); - const responsePost = await axios.get('http://localhost:8080/post'); + const responsePost = await axios.get('http://localhost:8080/api/post'); responsePost.data.forEach(element => { this.posts.splice(0, 0, element); console.log(element); diff --git a/src/main/java/np/something/DTO/CommentDto.java b/src/main/java/np/something/DTO/CommentDto.java index f34b93d..589efdf 100644 --- a/src/main/java/np/something/DTO/CommentDto.java +++ b/src/main/java/np/something/DTO/CommentDto.java @@ -2,29 +2,37 @@ package np.something.DTO; import np.something.model.Comment; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonProperty; import java.time.format.DateTimeFormatter; public class CommentDto { - public final long id; - public final String content; - public final String customerName; - public final String postTitle; - public final String postAuthor; - public final long postAuthorId; + public long id; + public String content; + public long customerId; + public String customerName; + public long postId; + public String postTitle; + public String postAuthor; + public long postAuthorId; + public String createDate; - public final String createDate; + public CommentDto() { + + } public CommentDto(Comment comment) { this.id = comment.getId(); this.content = comment.getContent(); + this.customerId = comment.getCustomer().getId(); this.customerName = comment.getCustomer().getUsername(); + this.postId = comment.getPost().getId(); this.postTitle = comment.getPost().getTitle(); this.postAuthor = comment.getPost().getCustomer().getUsername(); this.postAuthorId = comment.getPost().getCustomer().getId(); this.createDate = comment.getCreateDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public long getId() { return id; } @@ -33,20 +41,33 @@ public class CommentDto { return content; } + public long getCustomerId() { + return customerId; + } + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getCustomerName() { return customerName; } + public long getPostId() { + return postId; + } + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getPostTitle() {return postTitle;} + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getPostAuthor() { return postAuthor; } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public long getPostAuthorId() { return postAuthorId; } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getCreateDate() { return createDate; } diff --git a/src/main/java/np/something/DTO/CustomerDto.java b/src/main/java/np/something/DTO/CustomerDto.java index c688b09..5fb7b6b 100644 --- a/src/main/java/np/something/DTO/CustomerDto.java +++ b/src/main/java/np/something/DTO/CustomerDto.java @@ -1,15 +1,21 @@ package np.something.DTO; +import com.fasterxml.jackson.annotation.JsonProperty; import np.something.model.Customer; +import java.io.Serializable; import java.util.List; public class CustomerDto { - public final long id; - public final String username; - public final String password; - public final List comments; - public final List posts; + public long id; + public String username; + public String password; + public List comments; + public List posts; + + public CustomerDto() { + + } public CustomerDto(Customer customer) { this.id = customer.getId(); @@ -19,6 +25,7 @@ public class CustomerDto { this.posts = customer.getPosts().stream().map(PostDto::new).toList(); } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public long getId() { return id; } @@ -31,10 +38,12 @@ public class CustomerDto { return password; } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public List getComments() { return comments; } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public List getPosts() { return posts; } diff --git a/src/main/java/np/something/DTO/PostDto.java b/src/main/java/np/something/DTO/PostDto.java index 0a82e33..73239a0 100644 --- a/src/main/java/np/something/DTO/PostDto.java +++ b/src/main/java/np/something/DTO/PostDto.java @@ -1,5 +1,6 @@ package np.something.DTO; +import com.fasterxml.jackson.annotation.JsonProperty; import np.something.model.Post; import java.time.LocalDateTime; @@ -7,16 +8,19 @@ import java.time.format.DateTimeFormatter; import java.util.List; public class PostDto { - public final long id; - public final String title; - public final String content; - public final String customerName; - - public final long customerId; - public final List comments; + public long id; + public String title; + public String content; + public String customerName; + public long customerId; + public List comments; public String createDate; + public PostDto() { + + } + public PostDto(Post post) { this.id = post.getId(); this.title = post.getTitle(); @@ -27,6 +31,7 @@ public class PostDto { this.createDate = post.getCreateDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public long getId() { return id; } @@ -39,10 +44,12 @@ public class PostDto { return content; } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getCustomerName() { return customerName; } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public List getComments() { return comments; } @@ -51,6 +58,7 @@ public class PostDto { return customerId; } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) public String getCreateDate() { return createDate; } diff --git a/src/main/java/np/something/WebConfiguration.java b/src/main/java/np/something/WebConfiguration.java index 7b95d8d..b5e8c55 100644 --- a/src/main/java/np/something/WebConfiguration.java +++ b/src/main/java/np/something/WebConfiguration.java @@ -6,6 +6,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfiguration implements WebMvcConfigurer { + public static final String REST_API = "/api"; + @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedMethods("*"); diff --git a/src/main/java/np/something/controllers/CommentController.java b/src/main/java/np/something/controllers/CommentController.java index 7f77e86..b88054d 100644 --- a/src/main/java/np/something/controllers/CommentController.java +++ b/src/main/java/np/something/controllers/CommentController.java @@ -1,6 +1,8 @@ package np.something.controllers; +import jakarta.validation.Valid; import np.something.DTO.CommentDto; +import np.something.WebConfiguration; import np.something.model.Comment; import np.something.services.*; import org.springframework.web.bind.annotation.*; @@ -8,7 +10,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; @RestController -@RequestMapping("/comment") +@RequestMapping(WebConfiguration.REST_API + "/comment") public class CommentController { private final CommentService commentService; private final CustomerService customerService; @@ -33,14 +35,18 @@ public class CommentController { } @PostMapping - public CommentDto createComment(@RequestParam("text") String text, @RequestParam("ownerId") Long ownerId, @RequestParam("postId") Long postId){ - final Comment comment = commentService.addComment(customerService.findCustomer(ownerId), postService.findPost(postId), text); + public CommentDto createComment(@RequestBody @Valid CommentDto commentDto){ + final Comment comment = commentService.addComment( + customerService.findCustomer(commentDto.getCustomerId()), + postService.findPost(commentDto.getPostId()), + commentDto.getContent() + ); return new CommentDto(comment); } @PutMapping("/{id}") - public CommentDto updateComment(@RequestParam("text") String text, @PathVariable Long id) { - return new CommentDto(commentService.updateComment(id, text)); + public CommentDto updateComment(@RequestBody @Valid CommentDto commentDto, @PathVariable Long id) { + return new CommentDto(commentService.updateComment(id, commentDto.getContent())); } @DeleteMapping("/{id}") diff --git a/src/main/java/np/something/controllers/CustomerController.java b/src/main/java/np/something/controllers/CustomerController.java index b3cfb3e..b693df5 100644 --- a/src/main/java/np/something/controllers/CustomerController.java +++ b/src/main/java/np/something/controllers/CustomerController.java @@ -1,6 +1,8 @@ package np.something.controllers; +import jakarta.validation.Valid; import np.something.DTO.CustomerDto; +import np.something.WebConfiguration; import np.something.model.Customer; import np.something.services.*; import org.springframework.web.bind.annotation.*; @@ -8,7 +10,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; @RestController -@RequestMapping("/customer") +@RequestMapping(WebConfiguration.REST_API + "/customer") public class CustomerController { private final CustomerService customerService; @@ -29,14 +31,14 @@ public class CustomerController { } @PostMapping - public CustomerDto createCustomer(@RequestParam("username") String username, @RequestParam("password") String password){ - final Customer customer = customerService.addCustomer(username, password); + public CustomerDto createCustomer(@RequestBody @Valid CustomerDto customerDto){ + final Customer customer = customerService.addCustomer(customerDto.getUsername(), customerDto.getPassword()); return new CustomerDto(customer); } @PutMapping("/{id}") - public CustomerDto updateCustomer(@RequestParam("username") String username, @RequestParam("password") String password, @PathVariable Long id) { - return new CustomerDto(customerService.updateCustomer(id, username, password)); + public CustomerDto updateCustomer(@RequestBody @Valid CustomerDto customerDto, @PathVariable Long id) { + return new CustomerDto(customerService.updateCustomer(id, customerDto.getUsername(), customerDto.getPassword())); } @DeleteMapping("/{id}") diff --git a/src/main/java/np/something/controllers/PostController.java b/src/main/java/np/something/controllers/PostController.java index 260f422..6d3977e 100644 --- a/src/main/java/np/something/controllers/PostController.java +++ b/src/main/java/np/something/controllers/PostController.java @@ -1,13 +1,15 @@ package np.something.controllers; +import jakarta.validation.Valid; import np.something.DTO.PostDto; +import np.something.WebConfiguration; import np.something.services.CustomerService; import np.something.services.PostService; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController -@RequestMapping("/post") +@RequestMapping(WebConfiguration.REST_API + "/post") public class PostController { private final PostService postService; private final CustomerService customerService; @@ -30,23 +32,15 @@ public class PostController { } @PostMapping - public PostDto createPost( - @RequestParam("title") String title, - @RequestParam("content") String content, - @RequestParam("authorId") Long authorId - ) + public PostDto createPost(@RequestBody @Valid PostDto postDto) { - return new PostDto(postService.addPost(customerService.findCustomer(authorId), title, content)); + return new PostDto(postService.addPost(customerService.findCustomer(postDto.getCustomerId()), postDto.getTitle(), postDto.getContent())); } @PutMapping("/{id}") - public PostDto updatePost( - @PathVariable Long id, - @RequestParam("title") String title, - @RequestParam("content") String content - ) + public PostDto updatePost(@RequestBody @Valid PostDto postDto, @PathVariable Long id) { - return new PostDto(postService.updatePost(id, title, content)); + return new PostDto(postService.updatePost(id, postDto.title, postDto.content)); } @DeleteMapping("/{id}") diff --git a/src/main/java/np/something/util/error/AdviceController.java b/src/main/java/np/something/util/error/AdviceController.java index 55ab6bf..2c58f64 100644 --- a/src/main/java/np/something/util/error/AdviceController.java +++ b/src/main/java/np/something/util/error/AdviceController.java @@ -10,10 +10,11 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; import java.util.stream.Collectors; -@ControllerAdvice +@ControllerAdvice(annotations = RestController.class) public class AdviceController { @ExceptionHandler({ CommentNotFoundException.class,