可正常启动

This commit is contained in:
dengqichen 2024-11-29 17:34:20 +08:00
parent c913ab3cc5
commit 1afd981805
19 changed files with 595 additions and 131 deletions

View File

@ -4,7 +4,6 @@ import com.qqchen.deploy.backend.dto.TenantDTO;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.dto.query.TenantQuery;
import com.qqchen.deploy.backend.entity.Tenant;
import com.qqchen.deploy.backend.service.ITenantService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -15,13 +14,6 @@ import java.util.List;
@RequestMapping("/api/v1/tenant")
public class TenantApiController extends BaseController<Tenant, TenantDTO, Long, TenantQuery> {
protected final ITenantService service;
public TenantApiController(ITenantService service) {
super(service);
this.service = service;
}
@Override
protected void exportData(HttpServletResponse response, List<TenantDTO> data) {

View File

@ -11,6 +11,7 @@ import com.qqchen.deploy.backend.dto.request.LoginRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse;
import com.qqchen.deploy.backend.service.IUserService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -23,12 +24,9 @@ import java.util.List;
@RequestMapping("/api/v1/users")
public class UserApiController extends BaseController<User, UserDTO, Long, UserQuery> {
private final IUserService userService;
@Resource
private IUserService userService;
public UserApiController(IUserService userService) {
super(userService);
this.userService = userService;
}
@Operation(summary = "用户登录")
@PostMapping("/login")

View File

@ -3,7 +3,6 @@ package com.qqchen.deploy.backend.controller;
import com.qqchen.deploy.backend.dto.query.TenantQuery;
import com.qqchen.deploy.backend.entity.Tenant;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.service.ITenantService;
import com.qqchen.deploy.backend.dto.TenantDTO;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
@ -14,13 +13,9 @@ import java.io.OutputStream;
import java.util.List;
@RestController
@RequestMapping("/tenants")
@RequestMapping("/tenant")
public class TenantController extends BaseController<Tenant, TenantDTO, Long, TenantQuery> {
public TenantController(ITenantService service) {
super(service);
}
@Override
protected void exportData(HttpServletResponse response, List<TenantDTO> data) {
response.setContentType("application/vnd.ms-excel");

View File

@ -1,32 +1,19 @@
//package com.qqchen.deploy.backend.controller;
//
//import com.qqchen.deploy.backend.api.UserApiController;
//import com.qqchen.deploy.backend.framework.api.Response;
//import com.qqchen.deploy.backend.converter.UserConverter;
//import com.qqchen.deploy.backend.service.IUserService;
//import org.springframework.web.bind.annotation.GetMapping;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestParam;
//import org.springframework.web.bind.annotation.RestController;
//
//@RestController
//@RequestMapping("/mgmt/users")
//public class UserController extends UserApiController {
//
// protected final IUserService userService;
//
// public UserController(IUserService userService, UserConverter converter) {
// super(userService, converter);
// this.userService = userService;
// }
//
// @GetMapping("/check-username")
// public Response<Boolean> checkUsername(@RequestParam String username) {
// return Response.success(userService.checkUsernameExists(username));
// }
//
// @GetMapping("/check-email")
// public Response<Boolean> checkEmail(@RequestParam String email) {
// return Response.success(userService.checkEmailExists(email));
// }
//}
package com.qqchen.deploy.backend.controller;
import com.qqchen.deploy.backend.api.UserApiController;
import com.qqchen.deploy.backend.dto.UserDTO;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/mgmt/users")
public class UserController extends UserApiController {
@Override
protected void exportData(HttpServletResponse response, List<UserDTO> data) {
}
}

View File

@ -7,8 +7,12 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class RoleDTO extends BaseDTO {
private String name;
private String code;
private String description;
private Integer sort;
}

View File

@ -8,12 +8,20 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
public class TenantDTO extends BaseDTO {
private String name;
private String code;
private String description;
private Boolean enabled;
private String contactName;
private String contactPhone;
private String contactEmail;
private String address;
private String remark;
}

View File

@ -3,15 +3,21 @@ package com.qqchen.deploy.backend.dto;
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Set;
@Data
@EqualsAndHashCode(callSuper = true)
public class UserDTO extends BaseDTO {
private String username;
private String nickname;
private String email;
private String phone;
private Boolean enabled;
private Set<RoleDTO> roles;
}

View File

@ -0,0 +1,27 @@
package com.qqchen.deploy.backend.framework.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ServiceType {
Type value() default Type.DATABASE;
enum Type {
/**
* 数据库服务需要注入Repository和Converter
*/
DATABASE,
/**
* 集成服务不需要数据库操作
*/
INTEGRATION,
/**
* 混合服务可以选择性注入
*/
HYBRID
}
}

View File

@ -0,0 +1,165 @@
package com.qqchen.deploy.backend.framework.config;
import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.framework.utils.PackageScanner;
import com.qqchen.deploy.backend.framework.utils.ReflectionUtils;
import com.qqchen.deploy.backend.framework.utils.SpringUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.core.GenericTypeResolver;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Slf4j
public class ControllerBeanPostProcessor implements BeanPostProcessor, DisposableBean {
private final ApplicationContext applicationContext;
private final Map<Class<?>, IBaseService<?, ?, ?>> serviceCache = new ConcurrentHashMap<>();
public ControllerBeanPostProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
@SuppressWarnings("unchecked")
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof BaseController<?, ?, ?, ?> controller)) {
return bean;
}
try {
return injectService(controller, beanName);
} catch (ServiceInjectionException e) {
log.error("Service injection failed for controller: {}", beanName, e);
throw e;
} catch (Exception e) {
log.error("Unexpected error during service injection for controller: {}", beanName, e);
throw new BeanCreationException("Failed to inject service for controller: " + beanName, e);
}
}
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
Object injectService(BaseController<T, D, ID, ?> controller, String beanName) {
Class<T> entityClass = resolveEntityClass(controller);
if (entityClass == null) {
return controller;
}
IBaseService<?, ?, ?> cachedService = serviceCache.computeIfAbsent(
entityClass,
key -> findServiceForEntity(entityClass, beanName)
);
if (cachedService == null) {
throw new ServiceInjectionException("No service found for entity: " + entityClass.getSimpleName());
}
try {
IBaseService<T, D, ID> service = (IBaseService<T, D, ID>) cachedService;
ReflectionUtils.setField("service", controller, service);
log.debug("Successfully injected service {} for controller {}",
service.getClass().getSimpleName(),
controller.getClass().getSimpleName());
} catch (Exception e) {
throw new ServiceInjectionException("Failed to inject service field", e);
}
return controller;
}
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
Class<T> resolveEntityClass(BaseController<T, D, ID, ?> controller) {
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(
controller.getClass(), BaseController.class);
if (genericTypes == null || genericTypes.length < 3) {
log.warn("Could not resolve entity type for controller: {}",
controller.getClass().getSimpleName());
return null;
}
return (Class<T>) genericTypes[0];
}
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, ID extends Serializable>
IBaseService<?, ?, ?> findServiceForEntity(Class<T> entityClass, String controllerName) {
// 先尝试通过命名约定查找
String serviceBeanName = "i" + entityClass.getSimpleName() + "Service";
log.debug("Looking for service bean: {}", serviceBeanName);
if (applicationContext.containsBean(serviceBeanName)) {
return (IBaseService<?, ?, ?>) applicationContext.getBean(serviceBeanName);
}
// 如果找不到再通过类型匹配查找
log.debug("Service not found by name, trying to find by type matching");
return Arrays.stream(applicationContext.getBeanNamesForType(IBaseService.class))
.map(name -> tryGetService(name, entityClass, controllerName))
.filter(Objects::nonNull)
.findFirst()
.orElseThrow(() -> new ServiceInjectionException(
"No service found for entity: " + entityClass.getSimpleName() +
" (tried bean name: " + serviceBeanName + " and type matching)"));
}
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, ID extends Serializable>
IBaseService<?, ?, ?> tryGetService(String beanName, Class<T> entityClass, String controllerName) {
try {
Class<?> serviceClass = applicationContext.getType(beanName);
if (serviceClass == null) {
return null;
}
Class<?>[] serviceGenericTypes = GenericTypeResolver.resolveTypeArguments(
serviceClass, IBaseService.class);
if (serviceGenericTypes != null &&
serviceGenericTypes.length > 0 &&
entityClass.equals(serviceGenericTypes[0])) {
log.debug("Found matching service: {} for entity: {}", beanName, entityClass.getSimpleName());
return (IBaseService<?, ?, ?>) applicationContext.getBean(beanName);
}
} catch (Exception e) {
log.warn("Failed to analyze service bean: {} for controller: {}", beanName, controllerName, e);
}
return null;
}
@Override
public void destroy() {
serviceCache.clear();
}
public static class ServiceInjectionException extends BeanCreationException {
public ServiceInjectionException(String message) {
super(message);
}
public ServiceInjectionException(String message, Throwable cause) {
super(message, cause);
}
}
}

View File

@ -0,0 +1,114 @@
package com.qqchen.deploy.backend.framework.config;
import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import com.qqchen.deploy.backend.framework.utils.ReflectionUtils;
import com.querydsl.core.types.EntityPath;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.core.GenericTypeResolver;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.BeanCreationException;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
import java.lang.reflect.Field;
@Component
@Slf4j
public class ServiceBeanPostProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public ServiceBeanPostProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
@SuppressWarnings("unchecked")
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof BaseServiceImpl<?, ?, ?> service)) {
return bean;
}
try {
return injectDependencies(service, beanName);
} catch (Exception e) {
log.error("Failed to inject dependencies for service: {}", beanName, e);
throw new BeanCreationException("Failed to inject dependencies for service: " + beanName, e);
}
}
private <T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
Object injectDependencies(BaseServiceImpl<T, D, ID> service, String beanName) {
Class<T> entityClass = resolveEntityClass(service);
log.debug("Resolving dependencies for entity: {}", entityClass.getSimpleName());
try {
// 注入 Repository
String repositoryBeanName = "I" + entityClass.getSimpleName() + "Repository";
log.debug("Looking for repository bean: {}", repositoryBeanName);
if (!applicationContext.containsBean(repositoryBeanName)) {
throw new ControllerBeanPostProcessor.ServiceInjectionException("Repository not found: " + repositoryBeanName);
}
IBaseRepository<T, ID> repository = (IBaseRepository<T, ID>) applicationContext.getBean(repositoryBeanName);
ReflectionUtils.setField("repository", service, repository);
// 注入 Converter
String converterBeanName = entityClass.getSimpleName().substring(0, 1).toLowerCase()
+ entityClass.getSimpleName().substring(1) + "ConverterImpl";
log.debug("Looking for converter bean: {}", converterBeanName);
if (!applicationContext.containsBean(converterBeanName)) {
throw new ControllerBeanPostProcessor.ServiceInjectionException("Converter not found: " + converterBeanName);
}
BaseConverter<T, D> converter = (BaseConverter<T, D>) applicationContext.getBean(converterBeanName);
ReflectionUtils.setField("converter", service, converter);
// 初始化 EntityPath
try {
EntityPath<T> entityPath = initEntityPath(entityClass);
ReflectionUtils.setField("entityPath", service, entityPath);
} catch (Exception e) {
log.error("Failed to initialize EntityPath for {}", entityClass.getSimpleName(), e);
throw new ControllerBeanPostProcessor.ServiceInjectionException("Failed to initialize EntityPath: " + e.getMessage());
}
log.debug("Successfully injected all dependencies for service: {}", beanName);
return service;
} catch (ControllerBeanPostProcessor.ServiceInjectionException e) {
throw e;
} catch (Exception e) {
log.error("Unexpected error while injecting dependencies for {}", entityClass.getSimpleName(), e);
throw new ControllerBeanPostProcessor.ServiceInjectionException("Failed to inject dependencies: " + e.getMessage(), e);
}
}
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, ID extends Serializable> Class<T> resolveEntityClass(BaseServiceImpl<T, ?, ID> service) {
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(
service.getClass(), BaseServiceImpl.class);
if (genericTypes == null || genericTypes.length < 3) {
throw new IllegalStateException("Could not resolve entity type for service: "
+ service.getClass().getSimpleName());
}
return (Class<T>) genericTypes[0];
}
@SuppressWarnings("unchecked")
private <T extends Entity<ID>, ID extends Serializable> EntityPath<T> initEntityPath(Class<T> entityClass) {
try {
String qClassName = entityClass.getPackageName() + ".Q" + entityClass.getSimpleName();
Class<?> qClass = Class.forName(qClassName);
Field instanceField = qClass.getDeclaredField(entityClass.getSimpleName().toLowerCase());
return (EntityPath<T>) instanceField.get(null);
} catch (Exception e) {
throw new IllegalStateException("Failed to get Q class for " + entityClass.getName(), e);
}
}
}

View File

@ -6,7 +6,6 @@ import com.qqchen.deploy.backend.framework.query.BaseQuery;
import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.service.IBaseService;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.GenericTypeResolver;
import org.springframework.data.domain.Page;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -21,11 +20,7 @@ import java.util.concurrent.CompletableFuture;
@Validated
public abstract class BaseController<T extends Entity<ID>, D extends BaseDTO, ID extends Serializable, Q extends BaseQuery> {
protected final IBaseService<T, D, ID> service;
protected BaseController(IBaseService<T, D, ID> service) {
this.service = service;
}
protected IBaseService<T, D, ID> service;
@PostMapping
public Response<D> create(@Validated @RequestBody D dto) {
@ -78,6 +73,7 @@ public abstract class BaseController<T extends Entity<ID>, D extends BaseDTO, ID
/**
* 导出数据的具体实现
*
* @param response HTTP响应
* @param data 要导出的数据
*/

View File

@ -1,18 +1,26 @@
package com.qqchen.deploy.backend.framework.dto;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;
@Data
public class BaseDTO implements Serializable {
private Long id;
private LocalDateTime createTime;
private String createBy;
private LocalDateTime updateTime;
private String updateBy;
private Integer version;
private Boolean deleted;
// 扩展字段用于存储额外的属性

View File

@ -43,45 +43,29 @@ import jakarta.persistence.PersistenceContext;
import java.io.Serializable;
import java.lang.reflect.Field;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import com.qqchen.deploy.backend.framework.annotation.ServiceType;
@Transactional(readOnly = true)
@Slf4j
public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
implements IBaseService<T, D, ID> {
protected final IBaseRepository<T, ID> repository;
protected final BaseConverter<T, D> converter;
protected final EntityPath<T> entityPath;
protected IBaseRepository<T, ID> repository;
protected BaseConverter<T, D> converter;
protected EntityPath<T> entityPath;
@PersistenceContext
protected EntityManager entityManager;
protected BaseServiceImpl(IBaseRepository<T, ID> repository, BaseConverter<T, D> converter) {
this.repository = repository;
this.converter = converter;
this.entityPath = getEntityPath();
}
@SuppressWarnings("unchecked")
private EntityPath<T> getEntityPath() {
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class);
if (genericTypes == null || genericTypes.length < 2) {
throw new IllegalStateException("Could not resolve generic type arguments");
}
Class<T> entityClass = (Class<T>) genericTypes[0];
try {
String qClassName = entityClass.getPackageName() + ".Q" + entityClass.getSimpleName();
Class<?> qClass = Class.forName(qClassName);
Field instanceField = qClass.getDeclaredField(entityClass.getSimpleName().toLowerCase());
return (EntityPath<T>) instanceField.get(null);
} catch (Exception e) {
throw new RuntimeException("Failed to get Q class for " + entityClass.getName(), e);
}
}
@Override
@Transactional
public D create(D dto) {
validateDatabaseOperation("create");
T entity = converter.toEntity(dto);
T savedEntity = repository.save(entity);
return converter.toDto(savedEntity);
@ -90,6 +74,7 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, I
@Override
@Transactional
public D update(ID id, D dto) {
validateDatabaseOperation("update");
T entity = findEntityById(id);
converter.updateEntity(entity, dto);
T updatedEntity = repository.save(entity);
@ -99,25 +84,29 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, I
@Override
@Transactional
public void delete(ID id) {
validateDatabaseOperation("delete");
repository.deleteById(id);
}
@Override
public D findById(ID id) {
validateDatabaseOperation("findById");
T entity = findEntityById(id);
return converter.toDto(entity);
}
@Override
public List<D> findAll() {
validateDatabaseOperation("findAll");
List<T> entities = repository.findAll();
return converter.toDtoList(entities);
}
@Override
public List<D> findAll(BaseQuery query) {
validateDatabaseOperation("findAll");
if (query == null) {
return findAll(); // 如果查询参数为空返回所有数据
return findAll();
}
BooleanBuilder builder = createQueryPredicate(query);
Sort sort = createSort(query);
@ -127,6 +116,7 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, I
@Override
public Page<D> page(BaseQuery query) {
validateDatabaseOperation("page");
Page<T> page = repository.findAll(createQueryPredicate(query), createPageRequest(query));
return converter.toDtoPage(page);
}
@ -384,19 +374,20 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, I
try {
return update(id, dto);
} catch (OptimisticLockException e) {
// 重试前先刷新实体
entityManager.refresh(findEntityById(id));
throw e; // 抛出异常触发重试
throw e;
}
}
// 添加悲观锁查询方法
@Override
@Transactional
public T findByIdWithLock(ID id) {
validateDatabaseOperation("findByIdWithLock");
return repository.findByIdWithLock(id)
.orElseThrow(() -> new EntityNotFoundException(getEntityClass().getSimpleName(), id));
}
@Override
@SuppressWarnings("unchecked")
public Class<T> getEntityClass() {
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class);
@ -406,10 +397,18 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, I
throw new IllegalStateException("Could not resolve entity class");
}
// 内部实体操作方法
@Override
public T findEntityById(ID id) {
validateDatabaseOperation("findEntityById");
return repository.findById(id)
.orElseThrow(() -> new EntityNotFoundException(getEntityClass().getSimpleName(), id));
}
protected void validateDatabaseOperation(String operation) {
ServiceType serviceType = getClass().getAnnotation(ServiceType.class);
if (serviceType != null && serviceType.value() == ServiceType.Type.INTEGRATION) {
throw new UnsupportedOperationException(
"Database operation '" + operation + "' is not supported in integration service");
}
}
}

View File

@ -0,0 +1,37 @@
package com.qqchen.deploy.backend.framework.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashSet;
import java.util.Set;
@Slf4j
public class PackageScanner {
public static Set<String> scanControllerPackages(String basePackage) {
Set<String> packages = new HashSet<>();
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(RestController.class));
Set<BeanDefinition> components = scanner.findCandidateComponents(basePackage);
for (BeanDefinition component : components) {
String className = component.getBeanClassName();
if (className != null) {
try {
Class<?> clazz = Class.forName(className);
packages.add(clazz.getPackage().getName());
} catch (ClassNotFoundException e) {
log.warn("Failed to load class: {}", className, e);
}
}
}
return packages;
}
}

View File

@ -0,0 +1,86 @@
package com.qqchen.deploy.backend.framework.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import java.lang.reflect.Field;
@Slf4j
public class ReflectionUtils {
/**
* 设置字段值
*
* @param fieldName 字段名
* @param target 目标对象
* @param value
*/
public static void setField(String fieldName, Object target, Object value) {
Assert.notNull(fieldName, "Field name must not be null");
Assert.notNull(target, "Target object must not be null");
try {
Field field = findField(target.getClass(), fieldName);
if (field == null) {
throw new IllegalArgumentException(
"Could not find field [" + fieldName + "] on target [" + target.getClass().getName() + "]");
}
makeAccessible(field);
field.set(target, value);
} catch (Exception e) {
log.error("Failed to set field [{}] on target [{}]", fieldName, target.getClass().getName(), e);
throw new IllegalStateException("Failed to set field: " + fieldName, e);
}
}
/**
* 获取字段值
*
* @param fieldName 字段名
* @param target 目标对象
* @return 字段值
*/
public static Object getField(String fieldName, Object target) {
Assert.notNull(fieldName, "Field name must not be null");
Assert.notNull(target, "Target object must not be null");
try {
Field field = findField(target.getClass(), fieldName);
if (field == null) {
throw new IllegalArgumentException(
"Could not find field [" + fieldName + "] on target [" + target.getClass().getName() + "]");
}
makeAccessible(field);
return field.get(target);
} catch (Exception e) {
log.error("Failed to get field [{}] on target [{}]", fieldName, target.getClass().getName(), e);
throw new IllegalStateException("Failed to get field: " + fieldName, e);
}
}
/**
* 查找字段包括父类
*/
private static Field findField(Class<?> clazz, String fieldName) {
Class<?> searchType = clazz;
while (searchType != null && !Object.class.equals(searchType)) {
try {
return searchType.getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
searchType = searchType.getSuperclass();
}
}
return null;
}
/**
* 使字段可访问
*/
private static void makeAccessible(Field field) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
}
}

View File

@ -0,0 +1,47 @@
package com.qqchen.deploy.backend.framework.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
if (applicationContext == null) {
throw new IllegalStateException("ApplicationContext has not been initialized");
}
try {
return (T) applicationContext.getBean(name);
} catch (BeansException e) {
log.error("Failed to get bean by name: {}", name, e);
throw new IllegalStateException("Could not find bean: " + name, e);
}
}
public static <T> T getBean(Class<T> clazz) {
if (applicationContext == null) {
throw new IllegalStateException("ApplicationContext has not been initialized");
}
try {
return applicationContext.getBean(clazz);
} catch (BeansException e) {
log.error("Failed to get bean by class: {}", clazz.getName(), e);
throw new IllegalStateException("Could not find bean of type: " + clazz.getName(), e);
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}

View File

@ -14,9 +14,9 @@ import java.util.List;
@Service
public class TenantServiceImpl extends BaseServiceImpl<Tenant, TenantDTO, Long> implements ITenantService {
public TenantServiceImpl(ITenantRepository repository, TenantConverter converter) {
super(repository, converter);
}
// public TenantServiceImpl(ITenantRepository repository, TenantConverter converter) {
// super(repository, converter);
// }
// @Override
// public List<TenantDTO> findAll(BaseQuery query) {

View File

@ -1,5 +1,6 @@
package com.qqchen.deploy.backend.service.impl;
import com.qqchen.deploy.backend.framework.annotation.ServiceType;
import com.qqchen.deploy.backend.framework.audit.annotation.Audited;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
@ -28,28 +29,22 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE;
@Service
@ServiceType(DATABASE)
@Slf4j
public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implements IUserService {
private final UserConverter converter;
private final RoleConverter roleConverter;
@Resource
private RoleConverter roleConverter;
@Resource
private AuthenticationManager authenticationManager;
@Resource
private IUserRepository userRepository;
@Resource
private JwtTokenUtil jwtTokenUtil;
public UserServiceImpl(IUserRepository repository, UserConverter converter, RoleConverter roleConverter) {
super(repository, converter);
this.converter = converter;
this.roleConverter = roleConverter;
}
@Override
@Transactional(readOnly = false)
@Audited(action = "REGISTER", detail = "用户注册")
@ -83,26 +78,27 @@ public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implem
@Transactional(readOnly = true)
@Audited(action = "USER_LOGIN", detail = "登录")
public LoginResponse login(LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
);
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String token = jwtTokenUtil.generateToken(userDetails);
User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername())
.orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
LoginResponse response = new LoginResponse();
response.setId(user.getId());
response.setUsername(user.getUsername());
response.setNickname(user.getNickname());
response.setEmail(user.getEmail());
response.setPhone(user.getPhone());
response.setToken(token);
log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
return response;
// Authentication authentication = authenticationManager.authenticate(
// new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
// );
//
// UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// String token = jwtTokenUtil.generateToken(userDetails);
//
// User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername())
// .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
//
// LoginResponse response = new LoginResponse();
// response.setId(user.getId());
// response.setUsername(user.getUsername());
// response.setNickname(user.getNickname());
// response.setEmail(user.getEmail());
// response.setPhone(user.getPhone());
// response.setToken(token);
//
// log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
// return response;
return null;
}
@Override

View File

@ -1,6 +1,5 @@
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/deploy-ease-platform?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true