crud編寫的四種方式
1 裸寫crud
待演示
2 extend AbstractCrudController
待演示
3 spring data rest
待演示
4 ControllerHelper
重點來了哈哈 直接上代碼
import com.alibaba.fastjson.JSON;
import com.st.cms.common.spring.jpa.AbstractEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.*;
import javax.persistence.EntityNotFoundException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import static org.springframework.beans.BeanUtils.getPropertyDescriptor;
import static org.springframework.beans.BeanUtils.getPropertyDescriptors;
/**
* @author yangrd
* @date 2019/3/1
**/
@Slf4j
@RestController
public class ControllerHelper implements ApplicationContextAware {
private MappingManager mappingManager;
@PostMapping("/{repository}")
public ResponseEntity create(@PathVariable String repository, @RequestBody String reqJSON) {
Optional<JpaRepository> jpaRepository = mappingManager.getJpaRepository(repository);
if (jpaRepository.isPresent()) {
Object object = mappingManager.getEntityObj(repository);
if (object instanceof AbstractEntity) {
((AbstractEntity) object).setId(UUID.randomUUID().toString());
}
Object req = JSON.parseObject(reqJSON, object.getClass());
BeanUtils.copyProperties(req, object);
jpaRepository.ifPresent(repo -> repo.saveAndFlush(object));
return ResponseEntity.status(HttpStatus.CREATED).build();
}
return ResponseEntity.notFound().build();
}
@DeleteMapping("/{repository}/{id}")
public ResponseEntity delete(@PathVariable String repository, @PathVariable String id) {
Optional<JpaRepository> jpaRepository = mappingManager.getJpaRepository(repository);
if (jpaRepository.isPresent()) {
jpaRepository.ifPresent(repo -> repo.deleteById(id));
return ResponseEntity.noContent().build();
}
return ResponseEntity.notFound().build();
}
@PutMapping("/{repository}/{id}")
public ResponseEntity update(@PathVariable String repository, @PathVariable String id, @RequestBody String reqJSON) {
Optional<JpaRepository> jpaRepository = mappingManager.getJpaRepository(repository);
if (jpaRepository.isPresent()) {
jpaRepository.ifPresent(repo -> repo.findById(id).ifPresent(db -> {
Object req = JSON.parseObject(reqJSON, db.getClass());
BeanUtils.copyProperties(req, db);
repo.saveAndFlush(db);
}));
return ResponseEntity.noContent().build();
}
return ResponseEntity.notFound().build();
}
@GetMapping("/{repository}/{id}")
public ResponseEntity get(@PathVariable String repository, @PathVariable String id) {
Optional<JpaRepository> jpaRepository = mappingManager.getJpaRepository(repository);
if (jpaRepository.isPresent()) {
Optional<Object> optional = jpaRepository.map(repo -> repo.findById(id)).orElseGet(() -> Optional.empty());
return optional.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
return ResponseEntity.notFound().build();
}
@GetMapping("/{repository}")
public ResponseEntity get(@PathVariable String repository, Pageable pageable) {
Optional<JpaRepository> jpaRepository = mappingManager.getJpaRepository(repository);
if (jpaRepository.isPresent()) {
return ResponseEntity.ok(jpaRepository.map(repo -> repo.findAll(pageable)).orElse(null));
}
return ResponseEntity.notFound().build();
}
class MappingManager {
private Map<String, JpaRepository> entity4Repositories = new HashMap<>();
private Map<String, Class> entity4Class = new HashMap<>();
MappingManager(ApplicationContext applicationContext) {
Map<String, JpaRepository> repositoryBeans = applicationContext.getBeansOfType(JpaRepository.class);
repositoryBeans.forEach((repositoryName, repositoryBean) -> {
Class entityClass = MappingSupport.getEntityClass(repositoryBean);
String entityClassName = MappingSupport.getEntityName(entityClass);
entity4Repositories.put(entityClassName, repositoryBean);
entity4Class.put(entityClassName, entityClass);
});
}
public Optional<JpaRepository> getJpaRepository(String repository) {
return Optional.ofNullable(entity4Repositories.get(repository));
}
public Object getEntityObj(String repository) {
return Optional.ofNullable(entity4Class.get(repository)).map(clazz -> {
try {
return clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}).orElseThrow(EntityNotFoundException::new);
}
}
static class MappingSupport {
static Class getEntityClass(JpaRepository jpaRepository) {
Type[] jpaInterfacesTypes = jpaRepository.getClass().getGenericInterfaces();
Type[] type = ((ParameterizedType) ((Class) jpaInterfacesTypes[0]).getGenericInterfaces()[0]).getActualTypeArguments();
return (Class) type[0];
}
static String getEntityName(Class clazz) {
String simpleName = clazz.getSimpleName();
return simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);
}
}
/**
* @author yangrd
* @date 2018/8/30
* @see org.springframework.beans.BeanUtils#copyProperties(Object, Object, Class, String...)
**/
static class BeanUtils {
public static <T> T map(Object source, Class<T> targetClass) {
T targetObj = null;
try {
targetObj = targetClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
copyProperties(source, targetObj);
return targetObj;
}
/**
* 只拷貝不爲null的屬性
*
* @param source the source bean
* @param target the target bean
* @throws BeansException if the copying failed
*/
public static void copyProperties(Object source, Object target) throws BeansException {
copyProperties(source, target, null, (String[]) null);
}
/**
* 只拷貝不爲null的屬性
*
* @param source the source bean
* @param target the target bean
* @param editable the class (or interface) to restrict property setting to
* @param ignoreProperties array of property names to ignore
* @throws BeansException if the copying failed
* @see BeanWrapper
*/
private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties)
throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null &&
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
if (value != null) {
//只拷貝不爲null的屬性 by zhao
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
}
} catch (Throwable ex) {
throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", ex);
}
}
}
}
}
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Assert.notNull(applicationContext, "");
this.mappingManager = new MappingManager(applicationContext);
}
}