compileOnly group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.2'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.2'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.2'
jwt.secret.key=7ZWt7ZW0OTntmZTsnbTtjIXtlZzqta3snYTrhIjrqLjshLjqs4TroZzrgpjslYTqsIDsnpDtm4zrpa3tlZzqsJzrsJzsnpDrpbzrp4zrk6TslrTqsIDsnpA=
@Slf4j
@Component
@RequiredArgsConstructor
public class JwtUtil {
/* 1. JWT Token ์์ฑ ํ์๊ฐ */
// Header Key ๊ฐ
public static final String AUTHORIZATION_HEADER = "Authorization";
// ์ฌ์ฉ์ ๊ถํ๊ฐ Key
public static final String AUTHORIZATION_KEY = "auth";
// JWT Token ์ธ์ฆ๋ฐฉ์ (Bearer + JWT Token ํจ๊ป ์ ์ก)
private static final String BEARER_PREFIX = "Bearer ";
// JWT Token ๋ง๋ฃ์๊ฐ
private static final long TOKEN_TIME = 60 * 60 * 1000L; // ms๊ธฐ์ค -> 1์๊ฐ
// application.properties -> JWT Secret Key ๋ถ๋ฌ์ด
@Value("${jwt.secret.key}")
private String secretKey;
// JWT Token ์์ฑ ๋ฐ ๊ฒ์ฆ Key ์ ์ฅ์ฉ๋
private Key key;
// JWT Token ์์ฑ(์ฌ์ธ)์๊ณ ๋ฆฌ์ฆ
private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// Spring Bean ์ด๊ธฐํ -> ์คํ๋๋ ๋ฉ์๋
@PostConstruct
public void init() {
// secretKey -> ๋์ฝ๋ฉ -> byte๋ฐฐ์ด์ ๋ด์
byte[] bytes = Base64.getDecoder().decode(secretKey);
// ๋์ฝ๋ฉ ํ byte๋ฐฐ์ด -> JWT Token ์๋ช
๋ฐ ๊ฒ์ฆ์ ํ์ํ key ์์ฑ
key = Keys.hmacShaKeyFor(bytes);
}
/* 2. Client Request Header -> JWT Token ๊ฐ์ ธ์ค๊ธฐ */
public String getToken(HttpServletRequest httpServletRequest) {
// Header์ ์๋ JWT Token -> clientToken์ ๋ด์
String clientToken = httpServletRequest.getHeader(AUTHORIZATION_HEADER);
// clientToken ์กด์ฌ + Bearer๋ก ์์ -> JWT Token ๊ฐ๋ง ์ถ์ถ
if (StringUtils.hasText(clientToken) && clientToken.startsWith(BEARER_PREFIX)) {
return clientToken.substring(7);
}
return null;
}
/* 3. JWT Token ์์ฑ */
public String createToken(String username, UserRoleEnum userRoleEnum) {
Date date = new Date();
return BEARER_PREFIX +
Jwts.builder()
.setSubject(username)
.claim(AUTHORIZATION_KEY, userRoleEnum)
.setExpiration(new Date(date.getTime() + TOKEN_TIME))
.setIssuedAt(date)
.signWith(key, signatureAlgorithm)
.compact();
}
/* 4. JWT Token ๊ฒ์ฆ */
public boolean validateToken(String token) {
try {
Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
return true;
} catch (SecurityException | MalformedJwtException exception) {
log.info("Invalid JWT signature, ์ ํจํ์ง ์๋ JWT ์๋ช
์
๋๋ค");
} catch (ExpiredJwtException exception) {
log.info("Expired JWT Token, ๋ง๋ฃ๋ JWT Token ์
๋๋ค");
} catch (UnsupportedJwtException exception) {
log.info("Unsupported JWT Token, ์ง์๋์ง ์๋ JWT Token ์
๋๋ค");
} catch (IllegalArgumentException exception) {
log.info("JWT claims is empty, ์๋ชป๋ JWT Token ์
๋๋ค");
}
return false;
}
/* 5. JWT Token -> ํ์์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ */
public Claims getUserInfoFromToken(String token) {
return Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
}
}
import org.springframework.beans.factory.annotation.Value;
โ @Value import๋ฌธ ์์ ์ ์ฉ๋ก๊ทธ์ธ์ฑ๊ณต โ HTTP Response Header์ JWT Token ์์ฑ ํ, ์ค์ด Client์๊ฒ ๋ณด๋
/* ์๋ถ๋ถ ์๋ต */
// ๋ก๊ทธ์ธ
@ResponseBody
@PostMapping("/login")
public String login(@RequestBody LoginRequestDto loginRequestDto, HttpServletResponse httpServletResponse) {
userService.login(loginRequestDto, httpServletResponse);
return "success";
}
/* ์๋ถ๋ถ ์๋ต */
// ๋ก๊ทธ์ธ
@Transactional(readOnly = true)
public void login(LoginRequestDto loginRequestDto, HttpServletResponse httpServletResponse) {
// 1. RequestDto -> ID/PW ๊ฐ์ ธ์ด
String username = loginRequestDto.getUsername();
String password = loginRequestDto.getPassword();
// 2. ํ์์ ํจ์ฑ๊ฒ์ฌ
User user = userRepository.findByUsername(username).orElseThrow(
() -> new IllegalArgumentException("๋ฑ๋ก๋ ์ฌ์ฉ์๊ฐ ์์ต๋๋ค")
);
// 3. ๋น๋ฐ๋ฒํธ์ ํจ์ฑ๊ฒ์ฌ
if (! user.getPassword().equals(password)) {
throw new IllegalArgumentException("๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ์ง ์์ต๋๋ค");
}
// 4. ๋ก๊ทธ์ธ์ฑ๊ณต -> Http Response Header์ JWT Token ๋ณด๋ด๊ธฐ
httpServletResponse.addHeader(JwtUtil.AUTHORIZATION_HEADER, jwtUtil.createToken(user.getUsername(), user.getRole()));
}
๐ ProductController.java
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ ์กฐํ
@GetMapping("/products")
public List<ProductResponseDto> getProducts(HttpServletRequest httpServletRequest) {
return productService.getProducts(httpServletRequest);
}
/* ๋ท๋ถ๋ถ ์๋ต */
๐ ProductService.java
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ ์กฐํ
@Transactional(readOnly = true)
public List<ProductResponseDto> getProducts(HttpServletRequest httpServletRequest) {
// 1. HTTP Request Header -> JWT Token ๊ฐ์ ธ์ค๊ธฐ
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
// 2. JWT Token ์๋๊ฒฝ์ฐ์๋ง -> ๊ด์ฌ์ํ ์กฐํ ๊ฐ๋ฅ
if (token != null) {
// 2-1. JWT Token ๊ฒ์ฆ
if (jwtUtil.validateToken(token)) {
// true -> Token์์ ์ฌ์ฉ์์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// 2-2. Token์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์์ ๋ณด -> DB์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค")
);
// 2-3. ์ฌ์ฉ์๊ถํ ADMIN ; ์ ์ฒด์กฐํ, USER ; ๋ณธ์ธ ๊ด์ฌ์ํ์กฐํ
UserRoleEnum userRoleEnum = user.getRole();
System.out.println("role = " + userRoleEnum);
List<ProductResponseDto> productResponseDtoList = new ArrayList<>();
List<Product> productList;
if (userRoleEnum == UserRoleEnum.USER) {
productList = productRepository.findAllByUserId(user.getId());
} else {
productList = productRepository.findAll();
}
for (Product product : productList) {
productResponseDtoList.add(ProductResponseDto.of(product));
}
return productResponseDtoList;
} else {
return null;
}
}
/* ๋ท๋ถ๋ถ ์๋ต */
๐ ProductController.java
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ ๋ฑ๋ก
@PostMapping("/products")
public ProductResponseDto createProduct(@RequestBody ProductRequestDto productRequestDto, HttpServletRequest httpServletRequest) {
return productService.createProduct(productRequestDto, httpServletRequest);
}
/* ๋ท๋ถ๋ถ ์๋ต */
๐ ProductService.java
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ ๋ฑ๋ก
@Transactional
public ProductResponseDto createProduct(ProductRequestDto productRequestDto, HttpServletRequest httpServletRequest) {
// 1. HTTP Request Header -> JWT Token ๊ฐ์ ธ์ค๊ธฐ
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
// 2. JWT Token ์๋๊ฒฝ์ฐ์๋ง -> ๊ด์ฌ์ํ ๋ฑ๋ก ๊ฐ๋ฅ
if (token != null) {
// 2-1. JWT Token ๊ฒ์ฆ
if (jwtUtil.validateToken(token)) {
// true -> Token์์ ์ฌ์ฉ์์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// 2-2. Token์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์์ ๋ณด -> DB์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค")
);
// 2-3. ์์ฒญ๋ฐ์ DTO -> DB์ ์ ์ฅํ ๊ฐ์ฒด์์ฑ
Product product = productRepository.saveAndFlush(Product.of(productRequestDto, user.getId()));
return ProductResponseDto.of(product);
} else {
return null;
}
}
/* ๋ท๋ถ๋ถ ์๋ต */
๐ ProductController.java
/* ์๋ถ๋ถ ์๋ต */
@PutMapping("/products/{id}")
public Long updateProduct(@PathVariable Long id, @RequestBody ProductMypriceRequestDto productMypriceRequestDto, HttpServletRequest httpServletRequest) {
return productService.updateProduct(id, productMypriceRequestDto, httpServletRequest);
}
/* ๋ท๋ถ๋ถ ์๋ต */
๐ ProductService.java
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ ์ต์ ๊ฐ ๋ฑ๋ก
@Transactional
public Long updateProduct(Long id, ProductMypriceRequestDto productMypriceRequestDto, HttpServletRequest httpServletRequest) {
// 1. HTTP Request Header -> JWT Token ๊ฐ์ ธ์ค๊ธฐ
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
// 2. JWT Token ์๋๊ฒฝ์ฐ์๋ง -> ๊ด์ฌ์ํ ๋ฑ๋ก ๊ฐ๋ฅ
if (token != null) {
// 2-1. JWT Token ๊ฒ์ฆ
if (jwtUtil.validateToken(token)) {
// true -> Token์์ ์ฌ์ฉ์์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// 2-2. Token์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์์ ๋ณด -> DB์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค")
);
Product product = productRepository.findByIdAndUserId(id, user.getId()).orElseThrow(
() -> new IllegalArgumentException("ํด๋น์ํ์ ์กด์ฌํ์ง ์์ต๋๋ค")
);
product.update(productMypriceRequestDto);
return product.getId();
} else {
return null;
}
}
/* ๋ท๋ถ๋ถ ์๋ต */
๊ตฌ๋ถ | ์ข ๋ฅ |
---|---|
ํ์ด์ง | - page : ์กฐํํ ํ์ด์ง ๋ฒํธ (1๋ถํฐ ์์) - size : ํ ํ์ด์ง์ ๋ณด์ฌ์ค ๋ด์ฉ ๊ฐฏ์ (10๊ฐ๋ก ๊ณ ์ ) |
์ ๋ ฌ | - sortBy (์ ๋ ฌํญ๋ชฉ) : id, title, lprice - isAsc (์ค๋ฆ์ฐจ์) : true โ asc ์ค๋ฆ์ฐจ์, false โ desc ๋ด๋ฆผ์ฐจ์ |
๊ธฐ๋ฅ | Method | URL | Request | Response |
---|---|---|---|---|
๋ฉ์ธํ์ด์ง | GET | /api/shop | - | index.html |
Query๋ก ์ํ๊ฒ์, ์ํ๊ฒ์๊ฒฐ๊ณผ ๋ชฉ๋ก๋ฐํ | GET | /api/search?query=๊ฒ์์ด | - | [ { ย ย "title" : String, ย ย "image" : String, ย ย "link" : String, ย ย "lprice" : int }, โขโขโข ] |
๊ด์ฌ์ํ ๋ฑ๋ก | POST | /api/products | Header Authorization : Bearer <JWT> { ย ย "title" : String, ย ย "image" : String, ย ย "link" : String, ย ย "lprice" : int } | { ย ย "id" : Long, ย ย "title" : String, ย ย "image" : String, ย ย "link" : String, ย ย "lprice" : int, ย ย "myprice" : int } |
๊ด์ฌ์ํ ์กฐํ | GET | /api/products?sortBy=String&isAsc=boolean&size=int&page=int | Header Authorization : Bearer <JWT> | Page<Product> |
๊ด์ฌ์ํ ์ต์ ๊ฐ ๋ฑ๋ก | PUT | /api/products/{id} | Header Authorization : Bearer <JWT> { ย ย "myprice" : int } | id |
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ ์กฐํ
@GetMapping("/products")
public Page<Product> getProducts(
@RequestParam("page") int page, // ์กฐํํ ํ์ด์ง ๋ฒํธ (1๋ถํฐ ์์)
@RequestParam("size") int size, // ํ ํ์ด์ง์ ๋ณด์ฌ์ค ๊ฐ์
@RequestParam("sortBy") String sortBy, // ์ ๋ ฌํญ๋ชฉ
@RequestParam("isAsc") boolean isAsc, // ์ค๋ฆ์ฐจ์(True), ๋ด๋ฆผ์ฐจ์(False)
HttpServletRequest httpServletRequest) {
return productService.getProducts(httpServletRequest, page-1, size, sortBy, isAsc);
}
/* ๋ท๋ถ๋ถ ์๋ต */
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ ์กฐํ
@Transactional(readOnly = true)
public Page<Product> getProducts(HttpServletRequest httpServletRequest,
int page, int size, String sortBy, boolean isAsc) {
// ํ์ด์ง
Sort.Direction direction = isAsc ? Sort.Direction.ASC : Sort.Direction.DESC;
Sort sort = Sort.by(direction, sortBy);
Pageable pageable = PageRequest.of(page, size, sort);
// 1. HTTP Request Header -> JWT Token ๊ฐ์ ธ์ค๊ธฐ
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
// 2. JWT Token ์๋๊ฒฝ์ฐ์๋ง -> ๊ด์ฌ์ํ ์กฐํ ๊ฐ๋ฅ
if (token != null) {
// 2-1. JWT Token ๊ฒ์ฆ
if (jwtUtil.validateToken(token)) {
// true -> Token์์ ์ฌ์ฉ์์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// 2-2. Token์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์์ ๋ณด -> DB์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค")
);
// 2-3. ์ฌ์ฉ์๊ถํ ADMIN ; ์ ์ฒด์กฐํ, USER ; ๋ณธ์ธ ๊ด์ฌ์ํ์กฐํ
UserRoleEnum userRoleEnum = user.getRole();
System.out.println("role = " + userRoleEnum);
Page<Product> productPage;
if (userRoleEnum == UserRoleEnum.USER) {
productPage = productRepository.findAllByUserId(user.getId(), pageable);
} else {
productPage = productRepository.findAll(pageable);
}
return productPage;
} else {
return null;
}
}
/* ๋ท๋ถ๋ถ ์๋ต */
/* ์๋ถ๋ถ ์๋ต */
public interface ProductRepository extends JpaRepository<Product, Long> {
Page<Product> findAllByUserId(Long userId, Pageable pageable);
Optional<Product> findByIdAndUserId(Long id, Long userId);
Page<Product> findAll(Pageable pageable);
}
/* ๋ท๋ถ๋ถ ์๋ต */
์๊ตฌ์ฌํญ | ๊ธฐ๋ฅ |
---|---|
ํด๋ ์์ฑ | - ํ์๋ณ ํด๋ ์ถ๊ฐ ๊ฐ๋ฅ - ํด๋ ์ถ๊ฐ ์, 1~N๊ฐ ํ๋ฒ์ ์ถ๊ฐ ๊ฐ๋ฅ |
ํด๋์ ๊ด์ฌ์ํ ์ฝ์ | - ๊ด์ฌ์ํ์ ํด๋ N๊ฐ์ ๋ค์ด๊ฐ ์ ์์ - ๊ด์ฌ์ํ์ด ๋ฑ๋ก๋๋ ์์ โ ์ด๋ ํด๋์๋ ์ ์ฅ โ |
ํด๋ ๋ณ ์กฐํ | - ํ์์ ํด๋ ๋ณ ๊ด์ฌ์ํ ์กฐํ ๊ฐ๋ฅ - ์ ์ฒด : ํด๋์ ์๊ด์์ด ํ์์ด ์ ์ฅํ ์ ์ฒด ๊ด์ฌ์ํ ์กฐํ - ํด๋๋ช : ํด๋ ๋ณ ์ ์ฅ๋ ๊ด์ฌ์ํ๋ง ์กฐํ ๊ฐ๋ฅ |
@OneToMany
public class User {
@OneToMany
private List<Folder> folderList;
}
// ํ์์ด ๊ฐ์ง ํด๋ ์กฐํ
List<Folder> folderList = user.getFolderList();
@ManyToOne
public class Folder {
@ManyToOne
private User user;
}
// ํด๋ ์์ ํ์ ์กฐํ
folder.getUser();
@ManyToOne
@JoinColumn(name = "USER_ID", nullable = false)
private User user;
// name : ์ธ๋ํค๋ช
// nullable : ์ธ๋ํค null ํ์ฉ์ฌ๋ถ
๊ธฐ๋ฅ | Method | URL | Request | Response |
---|---|---|---|---|
ํด๋ ์์ฑ | POST | api/folders | { ย ย "folderNames" : [String, โขโขโข] } | [String, โขโขโข] |
ํด๋ ์กฐํ | GET | api/user-folder | - | index.html model ์ถ๊ฐ โ folders |
/* ์๋ถ๋ถ ์๋ต */
@OneToMany
List<Folder> folders = new ArrayList<>();
/* ๋ท๋ถ๋ถ ์๋ต */
@Entity
@Getter
@NoArgsConstructor
public class Folder {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(nullable = false)
private String name;
@ManyToOne
@JoinColumn(name = "USER_ID", nullable = false)
private User user;
// ์์ฑ์
public Folder(String name, User user) {
this.name = name;
this.user = user;
}
}
@Getter
public class FolderRequestDto {
List<String> folderNames;
}
@RestController
@RequiredArgsConstructor
@RequestMapping("/api")
public class FolderController {
private final FolderService folderService;
// ํด๋ ์์ฑ
@PostMapping("/folders")
public List<Folder> addFolders(@RequestBody FolderRequestDto folderRequestDto, HttpServletRequest httpServletRequest) {
List<String> folderNames = folderRequestDto.getFolderNames();
return folderService.addFolders(folderNames, httpServletRequest);
}
}
@Service
@RequiredArgsConstructor
public class FolderService {
private final FolderRepository folderRepository;
private final UserRepository userRepository;
private final JwtUtil jwtUtil;
// ํด๋ ์์ฑ
@Transactional
public List<Folder> addFolders(List<String> folderNames, HttpServletRequest httpServletRequest) {
// Client Request -> Token ๊ฐ์ ธ์ค๊ธฐ
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
// Token ์ ํจ -> ํด๋์์ฑ ๊ฐ๋ฅ
if (token != null) {
// Token ๊ฒ์ฆ
if (jwtUtil.validateToken(token)) {
// ํ ํฐ -> ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// ํ ํฐ์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ DB ์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.")
);
List<Folder> folderList = new ArrayList<>();
for (String folderName : folderNames) {
Folder folder = new Folder(folderName, user);
folderList.add(folder);
}
return folderRepository.saveAll(folderList);
} else {
return null;
}
}
// ํด๋ ์กฐํ
public List<Folder> getFolders(HttpServletRequest httpServletRequest) {
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
if (token != null) {
if (jwtUtil.validateToken(token)) {
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// ํ ํฐ์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ DB ์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.")
);
return folderRepository.findAllByUser(user);
} else {
return null;
}
}
}
public interface FolderRepository extends JpaRepository<Folder, Long> {
List<Folder> findAllByUser(User user);
}
@Controller
@RequiredArgsConstructor
@RequestMapping("/api")
public class ShopController {
private final FolderService folderService;
@GetMapping("/shop")
public ModelAndView shop() {
return new ModelAndView("index");
}
// ๋ก๊ทธ์ธ ํ ์ ์ -> ๋ฉ์ธํ์ด์ง ์์ฒญ ์, ํด๋ ์๋ ์กฐํ
@GetMapping("/user-folder")
public String getUserInfo(Model model, HttpServletRequest httpServletRequest) {
model.addAttribute("folders", folderService.getFolders(httpServletRequest));
return "/index :: #fragment";
}
}
๐ Folder์ Product JPA ์ฐ๊ด๊ด๊ณ โก๏ธ
M : N
๊ด์ฌ์ํ โ ํด๋ 0 ~ N๊ฐ ์ค์ ๊ฐ๋ฅ
๊ด์ฌ์ํ ๋ฑ๋ก์์ โ ์ด๋ค ํด๋์๋ ์ ์ฅ โ
๊ด์ฌ์ํ โ ๊ธฐ ์์ฑ๋ ํด๋๋ฅผ ์ ํํด ์ถ๊ฐ๊ฐ๋ฅ
๊ธฐ๋ฅ | Method | URL | Request | Response |
---|---|---|---|---|
ํด๋ ์ ์ฒด ์กฐํ | GET | api/folders | - | [ { ย ย "id" : int, ย ย "name" : String, ย ย "user" : { ย ย ย ย "id" : int, ย ย ย ย "username" : String, ย ย ย ย "password" : String, ย ย ย ย "email" : String, ย ย ย ย "role" : String, ย ย ย ย "folders" : [] ย ย } }, โขโขโข ] |
๊ด์ฌ์ํ์ ํด๋ ์ถ๊ฐ | POST | api/products/{productId}/folder | {productId} : ๊ด์ฌ์ํ Id [Form ํํ] folderId : ์ถ๊ฐํ ํด๋ Id | ํด๋๊ฐ ์ถ๊ฐ ๋ ๊ด์ฌ์ํ Id |
/* ์๋ถ๋ถ ์๋ต */
// ํด๋ ์ ์ฒด ์กฐํ
@GetMapping("/folders")
public List<Folder> getFolders(HttpServletRequest httpServletRequest) {
return folderService.getFolders(httpServletRequest);
}
/* ๋ท๋ถ๋ถ ์๋ต */
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ์ ํด๋์ถ๊ฐ
@PostMapping("products/{productId}/folder")
public Long addFolder(@PathVariable Long productId, @RequestParam Long folderId, HttpServletRequest httpServletRequest) {
Product product = productService.addFolder(productId, folderId, httpServletRequest);
return product.getId();
}
/* ์๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ์ ํด๋์ถ๊ฐ
@Transactional
public Product addFolder(Long productId, Long folderId, HttpServletRequest httpServletRequest) {
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
if (token != null) {
if (jwtUtil.validateToken(token)) {
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// ์ฌ์ฉ์ ์ ํจ์ฑ๊ฒ์ฌ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค")
);
// ์ํ ์ ํจ์ฑ๊ฒ์ฌ
Product product = productRepository.findById(productId)
.orElseThrow( () -> new NullPointerException("ํด๋น ์ํ ์์ด๋๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค") );
// ํด๋ ์ ํจ์ฑ๊ฒ์ฌ
Folder folder = folderRepository.findById(folderId)
.orElseThrow( () -> new NullPointerException("ํด๋น ํด๋ ์์ด๋๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค") );
// ์ํ, ํด๋ -> ๊ฐ์ ํ์ ์์ ์ธ์ง ํ์ธ
Long loginUserId = user.getId();
if (! product.getUserId().equals(loginUserId) || ! folder.getUser().getId().equals(loginUserId)) {
throw new IllegalArgumentException("ํ์๋์ ๊ด์ฌ์ํ์ด ์๋๊ฑฐ๋, ํ์๋์ ํด๋๊ฐ ์๋๋๋ค");
}
product.addFolder(folder);
} else {
return null;
}
}
/* ์๋ถ๋ถ ์๋ต */
@ManyToMany
private List<Folder> folderList = new ArrayList<>();
/* ์ค๊ฐ๋ถ๋ถ ์๋ต */
// ๊ด์ฌ์ํ์ ํด๋์ถ๊ฐ
public void addFolder(Folder folder) {
this.folderList.add(folder);
}
/* ๋ท๋ถ๋ถ ์๋ต */
ํ์์ ํด๋ ๋ณ ๊ด์ฌ์ํ ์กฐํ๊ฐ๋ฅ
'ํด๋๋ณ' : ํด๋๋ณ ์ ์ฅ๋ ๊ด์ฌ์ํ ์กฐํ๊ฐ๋ฅ
'์ ์ฒด' : ํด๋์ ์๊ด์์ด ํ์์ด ์ ์ฅํ ์ ์ฒด ๊ด์ฌ์ํ ์กฐํ๊ฐ๋ฅ
๊ธฐ๋ฅ | Method | URL | Request | Response |
---|---|---|---|---|
ํด๋ ๋ณ ๊ด์ฌ์ํ ์กฐํ | GET | api/folders/{folderId}/products | {folderId} : ์กฐํ๋ฅผ ์ํ๋ ํด๋ Id | Page<Product> |
/* ์๋ถ๋ถ ์๋ต */
// ํด๋ ๋ณ ๊ด์ฌ์ํ ์กฐํ
@GetMapping("/folders/{folderId}/products")
public Page<Product> getProductsInFolder (@PathVariable Long folderId,
@RequestParam int page,
@RequestParam int size,
@RequestParam String sortBy,
@RequestParam boolean isAsc,
HttpServletRequest httpServletRequest) {
return folderService.getProductsInFolder(folderId, page-1, size, sortBy, isAsc, httpServletRequest);
}
/* ์๋ถ๋ถ ์๋ต */
@Transactional(readOnly = true)
public Page<Product> getProductsInFolder(Long folderId, int page, int size, String sortBy, boolean isAsc, HttpServletRequest httpServletRequest) {
// ํ์ด์ง ์ฒ๋ฆฌ
Sort.Direction direction = isAsc ? Sort.Direction.ASC : Sort.Direction.DESC;
Sort sort = Sort.by(direction, sortBy);
Pageable pageable = PageRequest.of(page, size, sort);
// Request์์ Token ๊ฐ์ ธ์ค๊ธฐ
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
// ํ ํฐ์ด ์๋ ๊ฒฝ์ฐ์๋ง ๊ด์ฌ์ํ ์กฐํ ๊ฐ๋ฅ
if (token != null) {
// Token ๊ฒ์ฆ
if (jwtUtil.validateToken(token)) {
// ํ ํฐ์์ ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// ํ ํฐ์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ DB ์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.")
);
return productRepository.findAllByUserIdAndFolderList_Id(user.getId(), folderId, pageable);
} else {
return null;
}
public interface ProductRepository extends JpaRepository<Product, Long> {
Page<Product> findAllByUserIdAndFolderList_Id(Long userId, Long folderId, Pageable);
}
private boolean isExistFolderName(String folderName, List<Folder> existFolderList) {
// ๊ธฐ์กด ํด๋ ๋ฆฌ์คํธ์์ folder name ์ด ์๋์ง ๊ฒ์ฌ
for (Folder existFolder : existFolderList) {
if (existFolder.getName().equals(folderName)) {
return true;
}
}
return false;
}
/* ํด๋์์ฑ addFolders ๋ฉ์๋ */
// ํด๋๋ช
์ค๋ณต๊ฒ์ฌ
List<Folder> existFolderList = folderRepository.findAllByUserAndNameIn(user, folderNames);
List<Folder> folderList = new ArrayList<>();
for (String folderName : folderNames) {
if (! isExistFolderName(folderName, existFolderList)) {
Folder folder = new Folder(folderName, user);
folderList.add(folder);
}
}
return folderRepository.saveAll(folderList);
/* ์๋ถ๋ถ ์๋ต */
List<Folder> findAllByUserAndNameIn(User user, List<String> names);
/* ๊ด์ฌ์ํ์ ํด๋์ถ๊ฐ addFolder ๋ฉ์๋ */
// ์ค๋ณตํ์ธ
Optional<Product> overlapFolder = productRepository.findbyIdAndFolderList_Id(product.getId(), folder.getId());
if (overlapFolder.isPresent()) {
throw new IllegalArgumentException("์ค๋ณต๋ ํด๋์
๋๋ค");
}
product.addFolder(folder);
/* ์๋ถ๋ถ ์๋ต */
Optional<Product> findByIdAndFolderList_Id(Long productId, Long folderId);
๋ก๊ทธ์ธ ํ User๊ฐ ๋ฉ์ธํ์ด์ง ์์ฒญ ์, ์ ์ ์ ์ด๋ฆ ๋ฐํ
ShopController.java
@GetMapping("/user-info")
@ResponseBody
public String getUserName(HttpServletRequest httpServletRequest) {
String token = jwtUtil.getToken(httpServletRequest);
Claims claims;
if (token != null) {
// Token ๊ฒ์ฆ
if (jwtUtil.validateToken(token)) {
// ํ ํฐ์์ ์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
claims = jwtUtil.getUserInfoFromToken(token);
} else {
throw new IllegalArgumentException("Token Error");
}
// ํ ํฐ์์ ๊ฐ์ ธ์จ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ์ฌ DB ์กฐํ
User user = userRepository.findByUsername(claims.getSubject()).orElseThrow(
() -> new IllegalArgumentException("์ฌ์ฉ์๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.")
);
return user.getUsername();
}else {
return "fail";
}
}