How to make controller endpoint to get two different objects in java spring?

后端 未结 3 642
臣服心动
臣服心动 2021-01-03 05:50

I have a server built with java and spring.

What i am trying to do is that my controller with the same endpoint will get two different objects.

This is an ex

3条回答
  •  醉梦人生
    2021-01-03 06:53

    This is a good time to use inheritance and Java Generics. It is worth noting, if your controller has any dependencies such as a @Service or @Repository, then those too must be generic.

    You might have a generic controller:

    abstract class GenericController {
    
        public abstract GenericService getService();
    
        @GetMapping
        public ResponseEntity> findAll() {
    
            return ResponseEntity.ok(getService().findAll());
        }
    
        @PostMapping
        public ResponseEntity save(T entity) {
    
            return ResponseEntity.ok(getService().save(entity));
        }
    
        // @DeleteMapping, @PutMapping
        // These mappings will automatically be inherited by
        // the child class. So in the case of findAll(), the API
        // will have a GET mapping on /category as well as a GET
        // mapping on /product. So, by defining and annotating the
        // CRUD operations in the parent class, they will automatically
        // become available in all child classes.
    }
    
    @Controller
    @RequestMapping("/category")
    class CategoryContr extends GenericController {
    
        @Autowired CategoryServ serv;
    
        @Override
        public GenericService getService() {
            return serv;
        }
    }
    
    @Controller
    @RequestMapping("/product")
    class ProductContr extends GenericController {
    
        @Autowired ProductServ serv;
    
        @Override
        public GenericService getService() {
            return serv;
        }
    }
    

    You then have to have abstract versions of the dependencies. The services:

    abstract class GenericService {
    
        public abstract GenericRepository getRepository();
    
        public Iterable findAll() {
    
            return getRepository().findAll();
        }
    
        public T save(T entity) {
    
            return getRepository().save(entity);
        }
    
    }
    
    @Service
    class CategoryServ extends GenericService {
    
        @Autowired CategoryRepo repo;
    
        @Override
        public GenericRepository getRepository() {
            return repo;
        }
    }
    
    @Service
    class ProductServ extends GenericService {
    
        @Autowired ProductRepo repo;
    
        @Override
        public GenericRepository getRepository() {
            return repo;
        }
    }
    

    Then, the services have their dependencies as well - the repositories:

    @NoRepositoryBean
    interface GenericRepository extends JpaRepository {
    }
    
    @Repository
    interface CategoryRepo extends GenericRepository {
    }
    
    @Repository
    interface ProductRepo extends GenericRepository {
    }
    

    This was my first approach. It works very nicely. However, this does create a strong coupling between the business logic of each service and the generic service. The same holds true for the generic controller and its child classes. You can of course always override a particular CRUD operation. But, you must do this with care as you may created unexpected behavior. It is also worth noting that inheriting from classes that have methods that are annotated with @RequestMapping automatically exposes all of the annotated methods. This may be undesirable. For example, we may not want a delete option for categories, but we want it for products. To combat this, instead of annotating the method in the parent class, we can simply define it in the parent class, and override the desired CRUD operations with the added @RequestMapping annotation and then call the super class method.

    Another approach is using annotations.

提交回复
热议问题