Customizing HATEOAS link generation for entities with composite ids

前端 未结 4 1724
北荒
北荒 2020-12-05 12:08

I have configured a RepositoryRestResource on a PageAndSortingRepository that accesses an Entity that includes a composite Id:

@Ent         


        
4条回答
  •  攒了一身酷
    2020-12-05 12:40

    First, create a SpringUtil to get bean from spring.

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    @Component
    public class SpringUtil implements ApplicationContextAware {
        private static ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            if(SpringUtil.applicationContext == null) {
                SpringUtil.applicationContext = applicationContext;
            }
        }
    
        public static ApplicationContext getApplicationContext() {
            return applicationContext;
        }
    
        public static Object getBean(String name){
            return getApplicationContext().getBean(name);
        }
    
        public static  T getBean(Class clazz){
            return getApplicationContext().getBean(clazz);
        }
    
        public static  T getBean(String name,Class clazz){
            return getApplicationContext().getBean(name, clazz);
        }
    }
    

    Then, implement BackendIdConverter.

    import com.alibaba.fastjson.JSON;
    import com.example.SpringUtil;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.rest.webmvc.spi.BackendIdConverter;
    import org.springframework.stereotype.Component;
    
    import javax.persistence.EmbeddedId;
    import javax.persistence.Id;
    import java.io.Serializable;
    import java.io.UnsupportedEncodingException;
    import java.lang.reflect.Method;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    
    @Component
    public class CustomBackendIdConverter implements BackendIdConverter {
    
        @Override
        public boolean supports(Class delimiter) {
            return true;
        }
    
        @Override
        public Serializable fromRequestId(String id, Class entityType) {
            if (id == null) {
                return null;
            }
    
            //first decode url string
            if (!id.contains(" ") && id.toUpperCase().contains("%7B")) {
                try {
                    id = URLDecoder.decode(id, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
    
            //deserialize json string to ID object
            Object idObject = null;
            for (Method method : entityType.getDeclaredMethods()) {
                if (method.isAnnotationPresent(Id.class) || method.isAnnotationPresent(EmbeddedId.class)) {
                    idObject = JSON.parseObject(id, method.getGenericReturnType());
                    break;
                }
            }
    
            //get dao class from spring
            Object daoClass = null;
            try {
                daoClass = SpringUtil.getBean(Class.forName("com.example.db.dao." + entityType.getSimpleName() + "DAO"));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
    
            //get the entity with given primary key
            JpaRepository simpleJpaRepository = (JpaRepository) daoClass;
            Object entity = simpleJpaRepository.findOne((Serializable) idObject);
            return (Serializable) entity;
    
        }
    
        @Override
        public String toRequestId(Serializable id, Class entityType) {
            if (id == null) {
                return null;
            }
    
            String jsonString = JSON.toJSONString(id);
    
            String encodedString = "";
            try {
                encodedString = URLEncoder.encode(jsonString, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return encodedString;
        }
    }
    

    After that. you can do what you want.

    There is a sample below.

    • If the entity has single property pk, you can use localhost:8080/demo/1 as normal. According to my code, suppose the pk has annotation "@Id".
    • If the entity has composed pk, suppose the pk is demoId type, and has annotation "@EmbeddedId", you can use localhost:8080/demo/{demoId json} to get/put/delete. And your self link will be the same.

提交回复
热议问题