https://julian5383.tistory.com/94
[Spring] JPA로 블로그하고 데이터를 액세스 하기
https://julian5383.tistory.com/93 [Spring] MVC를 이용해 블로그 만들기 프로젝트를 생성합니다. Spring Boot DevTools, Lombok, Thymeleaf, Spring Web이 선택됩니다. Overview 옆에 있는 Dependencies로 들어..
julian5383.tistory.com
위 게시물 이후로 이어집니다.
2개의 RestController를 작성한다.
package com.aaa.blog.rest;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.RestController;
import com.aaa.blog.model.User;
import com.aaa.blog.service.UserService;
@RestController
@RequestMapping(value="/rest/user")
public class UserRestController {
@Autowired
private UserService userService;
@GetMapping(value="/getAll")
public ResponseEntity<List<User>> getAllPost(){
List<User> users = this.userService.findAll();
if (users == null || users.isEmpty()) {
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
@PostMapping(value="/login")
public ResponseEntity<Boolean> authenticate(@RequestBody Map<String, String> params, HttpSession session){
Boolean blogin = userService.authenticate(params.get("username"), params.get("password"));
if(!blogin) {
return new ResponseEntity<Boolean>(blogin, HttpStatus.FORBIDDEN);
}
session.setAttribute("username", params.get("username"));
return new ResponseEntity<Boolean>(blogin, HttpStatus.OK);
}
}
UserRestController.java
package com.aaa.blog.rest;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.aaa.blog.model.Post;
import com.aaa.blog.model.User;
import com.aaa.blog.service.PostService;
import com.aaa.blog.service.TagService;
import com.aaa.blog.service.UserService;
@RestController
@RequestMapping("/rest/post")
public class PostRestController {
@Autowired
private PostService postService;
@Autowired
private UserService userService;
@Autowired
private TagService tagService;
@GetMapping("getAll")
public ResponseEntity<List<Post>> getAllPost(){
List<Post> posts = this.postService.findAllOrderedById();
if (posts == null || posts.isEmpty()) {
return new ResponseEntity<List<Post>>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<List<Post>>(posts, HttpStatus.OK);
}
@GetMapping("get/{id}")
public ResponseEntity<Post> getPostById(@PathVariable("id")long id){
Optional<Post> optionalPost = this.postService.findById(id);
if(optionalPost.isPresent()) {
return new ResponseEntity<Post>(optionalPost.get(), HttpStatus.OK);
}
return new ResponseEntity<Post>(HttpStatus.NOT_FOUND);
}
@PostMapping("create")
public ResponseEntity<Post> create(@RequestBody Post post, HttpSession session){
post.setId(postService.findAllOrderedById().stream().map(Post::getId).max(Comparator.naturalOrder()).orElse(Long.MIN_VALUE)+1);
post.setUser(userService.findByUsername((String)session.getAttribute("username")).get());
Post p = this.postService.create(post);
if(p==null) {
return new ResponseEntity<Post>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Post>(p, HttpStatus.OK);
}
@PutMapping("put/{id}")
public ResponseEntity<Post> update(@PathVariable("id") long id, @RequestBody Post post){
Optional<Post> optionalPost = postService.findById(id);
if(optionalPost.isPresent()) {
Optional<User> optionalUser = userService.findById(optionalPost.get().getUser().getId());
if(optionalUser.isPresent()) {
Post updatePost = optionalPost.get();
updatePost.setId(id);
updatePost.setTitle(post.getTitle());
updatePost.setBody(post.getBody());
updatePost.setCreatedDate(new Date());
updatePost.setUser(optionalUser.get());
updatePost.setTags(tagService.getTags());
Post p = postService.edit(post);
if(p==null) {
return new ResponseEntity<Post>(post, HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Post>(post, HttpStatus.OK);
}
return new ResponseEntity<Post>(post, HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Post>(post, HttpStatus.NOT_FOUND);
}
@GetMapping("delete/{id}")
public ResponseEntity<Void> delete(@PathVariable("id") long id){
Optional<Post> optionalPost = postService.findById(id);
if (optionalPost.isPresent()) {
postService.deleteById(id);
}
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
PostRestController.java
User.java와 Post.java에 @Entity을 부여한 Model 클래스에서 관계형 데이터베이스에 매칭된 POJO객체를 Json 형태로 바인딩해 호출할 수 있도록 새로운 annotation을 추가한다.
package com.aaa.blog.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import org.hibernate.validator.constraints.Length;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name="BlogUser")
@JsonPropertyOrder({"id","username","email","fullname","role"})
// 전송될 Json 타입 data의 스키마를 지정
public class User {
@Id
@Column(name="USER_ID", nullable = false, unique = true)
@JsonProperty("User_ID") //Json으로 바인딩될 멤버변수를 설정
private Long id;
@Column(unique = true, nullable = false)
@Length(min=2, max=30, message="**아이디는 2자 이상 30자 이하입니다.")
@NotEmpty(message="**계정명을 입력해주세요")
private String username;
@Column(nullable = false)
@Length(min=5, message = "**암호를 5글자 이상으로 입력하세요")
@NotEmpty(message="**암호를 입력하세요")
@JsonIgnore //Json으로 바인딩될 때 해당 멤버변수를 제외
private String password;
@Column
@Email(message = "**유효한 이메일 계정을 입력해주세요")
@NotEmpty(message="**이메일 계정을 입력하세요")
private String email;
@Column
@NotEmpty(message = "**이름을 입력하세요")
private String fullname;
@Column
private UserRole role;
}
User.java
package com.aaa.blog.model;
import java.util.Collection;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotEmpty;
import org.hibernate.validator.constraints.Length;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table
public class Post {
@Id
@Column(name="POST_ID")
private Long id;
@Column(nullable = false)
@Length(min=5, max=30, message="**최소 5글자 이상 30글자 이하로 입력해주세요")
@NotEmpty(message="**제목을 입력하세요")
private String title;
@Lob
private String body;
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable = false, updatable = false)
@DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss")
private Date createdDate;
@ManyToOne
@JoinColumn(name="USER_ID", referencedColumnName = "USER_ID", nullable = false)
private User user;
@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE)
@JsonIgnoreProperties("post")
//Post 객체는 Tag객체를 포함하고 Tag객체 내에는 Post객체를 서로 포함하고 있어서
//RESTful 웹서비스에서 함수를 호출할때 무한루프에 빠짐, 이를 방지하기 위해 설정
private Collection<Tag> tags;
}
Post.java
Spring-Blog-Jpa 실행 후 웹 브라우저에 아래의 URL 입력하면 Json타입의 값을 반환한다.
http://localhost:8080/rest/user/getAll
http://localhost:8080/rest/post/get/3
혹은 http://localhost:8080/rest/post/delete/5로 Post를 삭제할 수 있습니다.
pom.xml으로 들어가서 jackson-dataformat-xml 의존체를 검색해 추가하고 저장한다.
UserRestController와 PostRestController에 몇 줄을 더 추가한다.
package com.aaa.blog.rest;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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.RestController;
import com.aaa.blog.model.User;
import com.aaa.blog.service.UserService;
@RestController
@RequestMapping(value="/rest/user")
public class UserRestController {
@Autowired
private UserService userService;
//@GetMapping(value="/getAll")
@GetMapping(value="/getAll", produces = {"application/xml","text/xml"}, consumes = MediaType.ALL_VALUE)
public ResponseEntity<List<User>> getAllPost(){
List<User> users = this.userService.findAll();
if (users == null || users.isEmpty()) {
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
return new ResponseEntity<List<User>>(users, HttpStatus.OK);
}
@PostMapping(value="/login")
public ResponseEntity<Boolean> authenticate(@RequestBody Map<String, String> params, HttpSession session){
Boolean blogin = userService.authenticate(params.get("username"), params.get("password"));
if(!blogin) {
return new ResponseEntity<Boolean>(blogin, HttpStatus.FORBIDDEN);
}
session.setAttribute("username", params.get("username"));
return new ResponseEntity<Boolean>(blogin, HttpStatus.OK);
}
}
UserRestController.java
package com.aaa.blog.rest;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.aaa.blog.model.Post;
import com.aaa.blog.model.User;
import com.aaa.blog.service.PostService;
import com.aaa.blog.service.TagService;
import com.aaa.blog.service.UserService;
@RestController
@RequestMapping("/rest/post")
public class PostRestController {
@Autowired
private PostService postService;
@Autowired
private UserService userService;
@Autowired
private TagService tagService;
//@GetMapping("getAll")
@GetMapping(value = "getAll", produces = {"application/xml", "text/xml"}, consumes = MediaType.ALL_VALUE)
public ResponseEntity<List<Post>> getAllPost(){
List<Post> posts = this.postService.findAllOrderedById();
if (posts == null || posts.isEmpty()) {
return new ResponseEntity<List<Post>>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<List<Post>>(posts, HttpStatus.OK);
}
//@GetMapping("get/{id}")
@GetMapping(value="get/{id}", produces = {"application/xml","text/xml"}, consumes = MediaType.ALL_VALUE)
public ResponseEntity<Post> getPostById(@PathVariable("id")long id){
Optional<Post> optionalPost = this.postService.findById(id);
if(optionalPost.isPresent()) {
return new ResponseEntity<Post>(optionalPost.get(), HttpStatus.OK);
}
return new ResponseEntity<Post>(HttpStatus.NOT_FOUND);
}
@PostMapping("create")
public ResponseEntity<Post> create(@RequestBody Post post, HttpSession session){
post.setId(postService.findAllOrderedById().stream().map(Post::getId).max(Comparator.naturalOrder()).orElse(Long.MIN_VALUE)+1);
post.setUser(userService.findByUsername((String)session.getAttribute("username")).get());
Post p = this.postService.create(post);
if(p==null) {
return new ResponseEntity<Post>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Post>(p, HttpStatus.OK);
}
@PutMapping("put/{id}")
public ResponseEntity<Post> update(@PathVariable("id") long id, @RequestBody Post post){
Optional<Post> optionalPost = postService.findById(id);
if(optionalPost.isPresent()) {
Optional<User> optionalUser = userService.findById(optionalPost.get().getUser().getId());
if(optionalUser.isPresent()) {
Post updatePost = optionalPost.get();
updatePost.setId(id);
updatePost.setTitle(post.getTitle());
updatePost.setBody(post.getBody());
updatePost.setCreatedDate(new Date());
updatePost.setUser(optionalUser.get());
updatePost.setTags(tagService.getTags());
Post p = postService.edit(post);
if(p==null) {
return new ResponseEntity<Post>(post, HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<Post>(post, HttpStatus.OK);
}
return new ResponseEntity<Post>(post, HttpStatus.NOT_FOUND);
}
return new ResponseEntity<Post>(post, HttpStatus.NOT_FOUND);
}
@GetMapping("delete/{id}")
public ResponseEntity<Void> delete(@PathVariable("id") long id){
Optional<Post> optionalPost = postService.findById(id);
if (optionalPost.isPresent()) {
postService.deleteById(id);
}
return new ResponseEntity<Void>(HttpStatus.OK);
}
}
PostRestController.java
다음 해당 링크를 통해서 Json 타입이 아닌 XML 형식으로 데이터를 반납한다.
http://localhost:8080/rest/user/getAll
http://localhost:8080/rest/post/get/3
static에 js파일과 html 파일을 넣는다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인 화면</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="/js/ajaxlogin.js"></script>
</head>
<body>
<h1>로그인 화면입니다.</h1>
<form method="post" id="loginForm" th:object="${loginForm}">
<div><label for="username">아이디</label></div>
<input id="username" type="text" name="username" th:value="*{username}"/>
<div><label for="password" th:value="*{username}">비밀번호</label></div>
<input id="password" type="password" name="password" th:value="*{password}" />
<div>
<input type="submit" value="로그인" />
<a href="index.html" th:href="@{/posts}">취소</a>
</div>
</form>
<div id=helloUserDiv></div>
</body>
</html>
ajaxlogin.html
$(document).ready(function () {
$("#loginForm").submit(function (event) {
event.preventDefault();
ajax_login_submit();
});
});
function ajax_login_submit() {
var user = {};
user["username"] = $("#username").val();
user["password"] = $("#password").val();
console.log(JSON.stringify(user));
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "rest/user/login",
data: JSON.stringify(user),
dataType: 'json',
cache : false,
success: function (data) {
$('#helloUserDiv').html('로그인 성공');
console.log("SUCCESS : ", data);
alert('로그인이 성공했습니다.');
},
error: function (e) {
var resultJson = e.responseText;
$('#helloUserDiv').html('로그인 실패');
console.log("ERROR : ", resultJson);
}
});
}
ajaxlogin.js
Spring-Blog-Jpa 프로젝트의 로그인 화면에서 환영 메시지를 표시하는 기능을 Ajax로 구현하였다.
https://github.com/Julian-Hwang/spring_boot_project/tree/main/Spring-Blog-Jpa
GitHub - Julian-Hwang/spring_boot_project
Contribute to Julian-Hwang/spring_boot_project development by creating an account on GitHub.
github.com
'Spring_boot > Project' 카테고리의 다른 글
[Spring] Bootstrap 적용하기 (0) | 2023.07.19 |
---|---|
[Spring] 스프링 보안 (0) | 2022.08.20 |
[Spring] JPA로 블로그하고 데이터를 액세스 하기 (0) | 2022.08.07 |
[Spring] MVC를 이용해 블로그 만들기 (0) | 2022.07.31 |
[Spring] Spring MVC와 Web Security 통합 (0) | 2021.08.29 |