Controller
- Controller에 Service를 연결시키는 부분도 CrudController로 추상화한다.
- 제네릭 타입으로 CrudController로 Req, Res, Entity 타입을 전달한다.
//com/example/study/controller/api/ItemApiController.java
@RestController
@RequestMapping("/api/item")
public class ItemApiController extends CrudController<ItemApiRequest, ItemApiResponse, Item> {
}
CrudController 추상 클래스
- Controller에서 제네릭 타입(Req, Res, Entity)을 받고 해당 엔티티에 해당되는 Service를 찾아 주입받는다.
- CrudInterface를 상속받아 CRUD 메소드를 구현한다.
@Component //@Autowired로 주입받기 위함
public abstract class CrudController<Req, Res, Entity> implements CrudInterface<Req, Res> {
//Controller에 Service를 연결시키는 부분
//Entity 타입에 해당되는 Service를 찾아 주입
@Autowired(required = false) //있을 수도 없을 수도 있음
protected BaseService<Req, Res, Entity> baseService;
@Override
@PostMapping("")
public Header<Res> create(@RequestBody Header<Req> request){
return baseService.create(request);
}
@Override
@GetMapping("{id}")
public Header<Res> read(@PathVariable Long id){
return baseService.read(id);
}
@Override
@PutMapping("")
public Header<Res> update(@RequestBody Header<Req> request){
return baseService.update(request);
}
@Override
@DeleteMapping("{id}")
public Header delete(@PathVariable Long id){
return baseService.delete(id);
}
}
Service
- Service에 Repository를 연결하는 부분을 BaseService로 추상화한다.
- 제네릭 타입으로 BaseService로 Req, Res, Entity 타입을 전달한다.
- 단, Service에서 CRUD에 대해서는 반드시 오버라이딩 해야한다.
//com/example/study/service/ItemApiLogicService.java
@Service
public class ItemApiLogicService extends BaseService<ItemApiRequest, ItemApiResponse, Item> {
@Autowired
private PartnerRepository partnerRepository;
@Override
public Header<ItemApiResponse> create(Header<ItemApiRequest> request) {
return Optional.ofNullable(request.getData())
.map(body -> {
Item item = Item.builder()
.status(body.getStatus())
.name(body.getName())
.title(body.getTitle())
.content(body.getContent())
.price(body.getPrice())
.brandName(body.getBrandName())
.registeredAt(LocalDateTime.now())
.partner(partnerRepository.getOne(body.getPartnerId()))
.build();
return item;
})
.map(newItem -> baseRepository.save(newItem)) //baseRepository 사용
.map(newItem -> response(newItem))
.orElseGet(() -> Header.ERROR("데이터 없음"));
}
//...
}
BaseService 추상 클래스
//com/example/study/service/BaseService.java
@Component //@Autowired로 주입받기 위함
public abstract class BaseService<Req, Res, Entity> implements CrudInterface<Req, Res> {
//Service에 Repository를 연결시키는 부분
//JpaRepository 중에 해당 Entity와 타입을 가진 Repository를 찾아 주입
@Autowired(required = false) //있을 수도 없을 수도 있음
protected JpaRepository<Entity, Long> baseRepository;
}