可正常启动

This commit is contained in:
dengqichen 2024-11-28 18:31:06 +08:00
parent 0826788fb8
commit bd8340355b
24 changed files with 654 additions and 557 deletions

View File

@ -1,33 +1,33 @@
package com.qqchen.deploy.backend.api; //package com.qqchen.deploy.backend.api;
//
import com.qqchen.deploy.backend.framework.api.Response; //import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.controller.BaseController; //import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.converter.TenantConverter; //import com.qqchen.deploy.backend.converter.TenantConverter;
import com.qqchen.deploy.backend.dto.query.TenantQuery; //import com.qqchen.deploy.backend.dto.query.TenantQuery;
import com.qqchen.deploy.backend.dto.request.TenantRequest; //import com.qqchen.deploy.backend.dto.request.TenantRequest;
import com.qqchen.deploy.backend.dto.response.TenantResponse; //import com.qqchen.deploy.backend.dto.response.TenantResponse;
import com.qqchen.deploy.backend.entity.Tenant; //import com.qqchen.deploy.backend.entity.Tenant;
import com.qqchen.deploy.backend.service.ITenantService; //import com.qqchen.deploy.backend.service.ITenantService;
import org.springframework.web.bind.annotation.GetMapping; //import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; //import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; //import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; //import org.springframework.web.bind.annotation.RestController;
//
@RestController //@RestController
@RequestMapping("/api/v1/tenant") //@RequestMapping("/api/v1/tenant")
public class TenantApiController extends BaseController<Tenant, Long, TenantQuery, TenantRequest, TenantResponse> { //public class TenantApiController extends BaseController<Tenant, Long, TenantQuery, TenantRequest, TenantResponse> {
//
protected final ITenantService service; // protected final ITenantService service;
//
public TenantApiController(ITenantService service, TenantConverter converter) { // public TenantApiController(ITenantService service, TenantConverter converter) {
super(service, converter); // super(service, converter);
this.service = service; // this.service = service;
} // }
//
@GetMapping("/code/{code}") // @GetMapping("/code/{code}")
public Response<TenantResponse> findByCode(@PathVariable String code) { // public Response<TenantResponse> findByCode(@PathVariable String code) {
Tenant tenant = service.findByCode(code); // Tenant tenant = service.findByCode(code);
return Response.success(converter.toResponse(tenant)); // return Response.success(converter.toResponse(tenant));
} // }
//
} //}

View File

@ -2,33 +2,30 @@ package com.qqchen.deploy.backend.api;
import com.qqchen.deploy.backend.framework.controller.BaseController; import com.qqchen.deploy.backend.framework.controller.BaseController;
import com.qqchen.deploy.backend.framework.api.Response; import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.converter.UserConverter;
import com.qqchen.deploy.backend.dto.request.LoginRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse;
import com.qqchen.deploy.backend.entity.User; import com.qqchen.deploy.backend.entity.User;
import com.qqchen.deploy.backend.dto.query.UserQuery; import com.qqchen.deploy.backend.dto.query.UserQuery;
import com.qqchen.deploy.backend.dto.request.UserRequest; import com.qqchen.deploy.backend.dto.request.UserRequest;
import com.qqchen.deploy.backend.dto.response.UserResponse; import com.qqchen.deploy.backend.dto.response.UserResponse;
import com.qqchen.deploy.backend.dto.request.UserRegisterRequest; import com.qqchen.deploy.backend.dto.request.LoginRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse;
import com.qqchen.deploy.backend.service.IUserService; import com.qqchen.deploy.backend.service.IUserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import org.springframework.data.domain.Page; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import java.io.IOException;
import org.springframework.web.bind.annotation.RequestMapping; import java.io.OutputStream;
import org.springframework.web.bind.annotation.RestController; import java.util.List;
@RestController @RestController
@RequestMapping("/api/v1/users") @RequestMapping("/api/v1/users")
public class UserApiController extends BaseController<User, Long, UserQuery, UserRequest, UserResponse> { public class UserApiController extends BaseController<User, Long, UserQuery, UserRequest, UserResponse> {
protected final IUserService userService; private final IUserService userService;
public UserApiController(IUserService userService, UserConverter converter) { public UserApiController(IUserService userService) {
super(userService, converter); super(userService);
this.userService = userService; this.userService = userService;
} }
@ -38,20 +35,21 @@ public class UserApiController extends BaseController<User, Long, UserQuery, Use
return Response.success(userService.login(request)); return Response.success(userService.login(request));
} }
@Operation(summary = "用户注册")
@PostMapping("/register") @PostMapping("/register")
public Response<UserResponse> register(@Validated @RequestBody UserRegisterRequest request) { public Response<UserResponse> register(@Validated @RequestBody UserRequest request) {
// 基础的注册逻辑 return Response.success(userService.register(request));
if (!request.getPassword().equals(request.getConfirmPassword())) { }
return Response.error(ResponseCode.USER_NOT_FOUND);
@Override
protected void exportData(HttpServletResponse response, List<UserResponse> data) {
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=users.xlsx");
try (OutputStream out = response.getOutputStream()) {
// ExcelUtils.export(data, out);
} catch (IOException e) {
throw new RuntimeException("Export failed", e);
} }
User user = converter.toEntity(request);
User savedUser = userService.register(user);
return Response.success(converter.toResponse(savedUser));
} }
@GetMapping("/page")
public Response<Page<UserResponse>> page(UserQuery query) {
return super.page(query);
}
} }

View File

@ -0,0 +1,19 @@
//package com.qqchen.deploy.backend.controller;
//
//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.request.TenantRequest;
//import com.qqchen.deploy.backend.dto.response.TenantResponse;
//import com.qqchen.deploy.backend.query.TenantQuery;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//
//@RestController
//@RequestMapping("/tenants")
//public class TenantController extends BaseController<Tenant, Long, TenantQuery, TenantRequest, TenantResponse> {
//
// public TenantController(ITenantService service) {
// super(service);
// }
//}

View File

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

View File

@ -9,5 +9,5 @@ import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) @Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface TenantConverter extends BaseConverter<Tenant, TenantRequest, TenantResponse> { public interface TenantConverter extends BaseConverter<Tenant, TenantRequest, TenantResponse> {
// MapStruct 会自动实现转换方法
} }

View File

@ -38,7 +38,7 @@ public class AppConfig {
} }
@Bean @Bean
public WebMvcConfigurer webMvcConfigurer(TenantInterceptor tenantInterceptor) { public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurer() { return new WebMvcConfigurer() {
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
@ -48,7 +48,7 @@ public class AppConfig {
registry.addInterceptor(localeChangeInterceptor); registry.addInterceptor(localeChangeInterceptor);
// 注册 TenantInterceptor // 注册 TenantInterceptor
registry.addInterceptor(tenantInterceptor).addPathPatterns("/**"); // Ensures it intercepts all requests // registry.addInterceptor(tenantInterceptor).addPathPatterns("/**"); // Ensures it intercepts all requests
} }
}; };
} }

View File

@ -1,7 +1,6 @@
package com.qqchen.deploy.backend.framework.controller; package com.qqchen.deploy.backend.framework.controller;
import com.qqchen.deploy.backend.framework.domain.Entity; import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
import com.qqchen.deploy.backend.framework.dto.BaseResponse; import com.qqchen.deploy.backend.framework.dto.BaseResponse;
import com.qqchen.deploy.backend.framework.query.BaseQuery; import com.qqchen.deploy.backend.framework.query.BaseQuery;
import com.qqchen.deploy.backend.framework.dto.BaseRequest; import com.qqchen.deploy.backend.framework.dto.BaseRequest;
@ -9,6 +8,7 @@ import com.qqchen.deploy.backend.framework.api.Response;
import com.qqchen.deploy.backend.framework.service.IBaseService; import com.qqchen.deploy.backend.framework.service.IBaseService;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.io.Serializable; import java.io.Serializable;
@ -18,29 +18,24 @@ import java.util.concurrent.CompletableFuture;
/** /**
* 通用REST控制器 * 通用REST控制器
*/ */
public abstract class BaseController<T extends Entity<ID>, ID extends Serializable, Q extends BaseQuery, REQ extends BaseRequest, RESP extends BaseResponse> { @Validated
public abstract class BaseController<T extends Entity<ID>, ID extends Serializable,
Q extends BaseQuery, REQ extends BaseRequest, RESP extends BaseResponse> {
protected final IBaseService<T, ID> service; protected final IBaseService<T, ID, REQ, RESP> service;
protected final BaseConverter<T, REQ, RESP> converter;
protected BaseController(IBaseService<T, ID> service, BaseConverter<T, REQ, RESP> converter) { protected BaseController(IBaseService<T, ID, REQ, RESP> service) {
this.service = service; this.service = service;
this.converter = converter;
} }
@PostMapping @PostMapping
public Response<RESP> create(@RequestBody REQ request) { public Response<RESP> create(@Validated @RequestBody REQ request) {
T entity = converter.toEntity(request); return Response.success(service.create(request));
T savedEntity = service.create(entity);
return Response.success(converter.toResponse(savedEntity));
} }
@PutMapping("/{id}") @PutMapping("/{id}")
public Response<RESP> update(@PathVariable ID id, @RequestBody REQ request) { public Response<RESP> update(@PathVariable ID id, @Validated @RequestBody REQ request) {
T entity = service.findById(id); return Response.success(service.update(id, request));
converter.updateEntity(entity, request);
T updatedEntity = service.update(entity);
return Response.success(converter.toResponse(updatedEntity));
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@ -51,26 +46,22 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
@GetMapping("/{id}") @GetMapping("/{id}")
public Response<RESP> findById(@PathVariable ID id) { public Response<RESP> findById(@PathVariable ID id) {
T entity = service.findById(id); return Response.success(service.findById(id));
return Response.success(converter.toResponse(entity));
} }
@GetMapping @GetMapping
public Response<List<RESP>> findAll() { public Response<List<RESP>> findAll() {
List<T> entities = service.findAll(); return Response.success(service.findAll());
return Response.success(converter.toResponseList(entities));
} }
@GetMapping("/page") @GetMapping("/page")
public Response<Page<RESP>> page(Q query) { public Response<Page<RESP>> page(Q query) {
Page<T> page = service.page(query); return Response.success(service.page(query));
return Response.success(page.map(entity -> converter.toResponse(entity)));
} }
@GetMapping("/list") @GetMapping("/list")
public Response<List<RESP>> findAll(Q query) { public Response<List<RESP>> findAll(Q query) {
List<T> entities = service.findAll(query); return Response.success(service.findAll(query));
return Response.success(converter.toResponseList(entities));
} }
@PostMapping("/batch") @PostMapping("/batch")
@ -81,8 +72,15 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
} }
@GetMapping("/export") @GetMapping("/export")
public void export(HttpServletResponse response, BaseQuery query) { public void export(HttpServletResponse response, Q query) {
List<T> data = service.findAll(query); List<RESP> data = service.findAll(query);
// 导出逻辑 exportData(response, data);
} }
/**
* 导出数据的具体实现
* @param response HTTP响应
* @param data 要导出的数据
*/
protected abstract void exportData(HttpServletResponse response, List<RESP> data);
} }

View File

@ -0,0 +1,26 @@
package com.qqchen.deploy.backend.framework.converter;
import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
import org.springframework.core.GenericTypeResolver;
public abstract class AbstractConverter<T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
implements BaseConverter<T, REQ, RESP> {
private final Class<T> entityClass;
@SuppressWarnings("unchecked")
protected AbstractConverter() {
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), AbstractConverter.class);
if (genericTypes == null || genericTypes.length < 3) {
throw new IllegalStateException("Could not resolve entity class");
}
this.entityClass = (Class<T>) genericTypes[0];
}
@Override
public Class<T> getEntityClass() {
return entityClass;
}
}

View File

@ -2,26 +2,39 @@ package com.qqchen.deploy.backend.framework.converter;
import com.qqchen.deploy.backend.framework.domain.Entity; import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseRequest; import com.qqchen.deploy.backend.framework.dto.BaseRequest;
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
import org.mapstruct.MappingTarget; import org.mapstruct.MappingTarget;
import org.springframework.core.GenericTypeResolver;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import java.util.List; import java.util.List;
public interface BaseConverter<D extends Entity<?>, R extends BaseRequest, V> { public interface BaseConverter<T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse> {
// Request -> Domain // Request -> Domain
D toEntity(R request); T toEntity(REQ request);
// Domain -> VO // Domain -> Response
V toResponse(D entity); RESP toResponse(T entity);
// Domain List -> VO List // Domain List -> Response List
List<V> toResponseList(List<D> entityList); List<RESP> toResponseList(List<T> entityList);
// 更新实体 // 更新实体
void updateEntity(@MappingTarget D entity, R request); void updateEntity(@MappingTarget T entity, REQ request);
// 转换分页结果 // 转换分页结果
default Page<V> toResponsePage(Page<D> page) { default Page<RESP> toResponsePage(Page<T> page) {
return page.map(this::toResponse); return page.map(this::toResponse);
} }
// 获取实体类类型
@SuppressWarnings("unchecked")
default Class<T> getEntityClass() {
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseConverter.class);
if (genericTypes == null || genericTypes.length < 3) {
throw new IllegalStateException("Could not resolve entity class");
}
return (Class<T>) genericTypes[0];
}
} }

View File

@ -0,0 +1,71 @@
package com.qqchen.deploy.backend.framework.converter;
import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class ConversionService {
private final Map<Class<?>, BaseConverter<?, ?, ?>> converterMap = new ConcurrentHashMap<>();
@Autowired
public void setConverters(List<BaseConverter<?, ?, ?>> converters) {
converters.forEach(converter -> {
Class<?> entityClass = converter.getEntityClass();
converterMap.put(entityClass, converter);
});
}
@SuppressWarnings("unchecked")
private <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
BaseConverter<T, REQ, RESP> getConverter(Class<T> entityClass) {
BaseConverter<?, ?, ?> converter = converterMap.get(entityClass);
if (converter == null) {
throw new IllegalArgumentException("No converter found for entity class: " + entityClass.getName());
}
return (BaseConverter<T, REQ, RESP>) converter;
}
@Cacheable(value = "conversion", key = "#request.class.name + '_' + #entityClass.name")
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
T toEntity(REQ request, Class<T> entityClass) {
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
return converter.toEntity(request);
}
@Cacheable(value = "conversion", key = "#entity.class.name + '_response'")
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
RESP toResponse(T entity) {
@SuppressWarnings("unchecked")
Class<T> entityClass = (Class<T>) entity.getClass();
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
return converter.toResponse(entity);
}
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
List<RESP> toResponseList(List<T> entities) {
if (entities.isEmpty()) {
return List.of();
}
@SuppressWarnings("unchecked")
Class<T> entityClass = (Class<T>) entities.get(0).getClass();
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
return converter.toResponseList(entities);
}
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
void updateEntity(T entity, REQ request) {
@SuppressWarnings("unchecked")
Class<T> entityClass = (Class<T>) entity.getClass();
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
converter.updateEntity(entity, request);
}
}

View File

@ -12,8 +12,8 @@ import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;
@Component //@Component
@Order(1) //@Order(1)
public class TenantFilter implements Filter { public class TenantFilter implements Filter {
@Override @Override

View File

@ -12,7 +12,7 @@ import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@Component //@Component
public class TenantInterceptor implements HandlerInterceptor { public class TenantInterceptor implements HandlerInterceptor {
private final AntPathMatcher pathMatcher = new AntPathMatcher(); private final AntPathMatcher pathMatcher = new AntPathMatcher();

View File

@ -1,6 +1,8 @@
package com.qqchen.deploy.backend.framework.service; package com.qqchen.deploy.backend.framework.service;
import com.qqchen.deploy.backend.framework.domain.Entity; import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
import com.qqchen.deploy.backend.framework.query.BaseQuery; import com.qqchen.deploy.backend.framework.query.BaseQuery;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
@ -10,22 +12,28 @@ import java.util.List;
/** /**
* 通用服务接口 * 通用服务接口
*/ */
public interface IBaseService<T extends Entity<ID>, ID extends Serializable> { public interface IBaseService<T extends Entity<ID>, ID extends Serializable, REQ extends BaseRequest, RESP extends BaseResponse> {
T create(T entity); RESP create(REQ request);
T update(T entity); RESP update(ID id, REQ request);
void delete(ID id); void delete(ID id);
T findById(ID id); RESP findById(ID id);
List<T> findAll(); List<RESP> findAll();
List<T> findAll(BaseQuery query); List<RESP> findAll(BaseQuery query);
Page<T> page(BaseQuery query); Page<RESP> page(BaseQuery query);
void batchProcess(List<T> entities); void batchProcess(List<T> entities);
T updateWithRetry(T entity); RESP updateWithRetry(ID id, REQ request);
T findEntityById(ID id);
T createEntity(T entity);
T updateEntity(T entity);
} }

View File

@ -9,7 +9,10 @@ import java.util.stream.Collectors;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.qqchen.deploy.backend.framework.annotation.LogicDelete; import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
import com.qqchen.deploy.backend.framework.converter.ConversionService;
import com.qqchen.deploy.backend.framework.domain.Entity; import com.qqchen.deploy.backend.framework.domain.Entity;
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
import com.qqchen.deploy.backend.framework.enums.QueryType; import com.qqchen.deploy.backend.framework.enums.QueryType;
import com.qqchen.deploy.backend.framework.query.BaseQuery; import com.qqchen.deploy.backend.framework.query.BaseQuery;
import com.qqchen.deploy.backend.framework.query.DateRange; import com.qqchen.deploy.backend.framework.query.DateRange;
@ -44,17 +47,19 @@ import java.lang.reflect.Field;
@Transactional(readOnly = true) @Transactional(readOnly = true)
@Slf4j @Slf4j
public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number & Serializable> implements IBaseService<T, ID> { public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number & Serializable,
REQ extends BaseRequest, RESP extends BaseResponse> implements IBaseService<T, ID, REQ, RESP> {
protected final IBaseRepository<T, ID> repository; protected final IBaseRepository<T, ID> repository;
protected final ConversionService conversionService;
protected final EntityPath<T> entityPath; protected final EntityPath<T> entityPath;
@PersistenceContext @PersistenceContext
protected EntityManager entityManager; protected EntityManager entityManager;
protected BaseServiceImpl(IBaseRepository<T, ID> repository) { protected BaseServiceImpl(IBaseRepository<T, ID> repository, ConversionService conversionService) {
this.repository = repository; this.repository = repository;
this.conversionService = conversionService;
this.entityPath = getEntityPath(); this.entityPath = getEntityPath();
} }
@ -77,25 +82,44 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
} }
@Override @Override
public Page<T> page(BaseQuery query) { public Page<RESP> page(BaseQuery query) {
BooleanBuilder builder = createQueryPredicate(query);
Page<T> page = repository.findAll(builder, createPageRequest(query));
return page.map(entity -> conversionService.toResponse(entity));
}
@Override
public List<RESP> findAll(BaseQuery query) {
BooleanBuilder builder = createQueryPredicate(query);
Sort sort = createSort(query);
List<T> entities = repository.findAllByCondition(builder, sort);
return conversionService.toResponseList(entities);
}
protected BooleanBuilder createQueryPredicate(BaseQuery query) {
BooleanBuilder builder = new BooleanBuilder().and(Expressions.asBoolean(true).isTrue()); BooleanBuilder builder = new BooleanBuilder().and(Expressions.asBoolean(true).isTrue());
if (query != null) { if (query != null) {
buildQueryPredicate(query, builder); buildQueryPredicate(query, builder);
} }
if (query == null || query.getDeleted() == null) { handleSoftDelete(builder);
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class); return builder;
if (genericTypes != null && genericTypes.length > 0) { }
Class<T> entityClass = (Class<T>) genericTypes[0];
LogicDelete softDelete = entityClass.getAnnotation(LogicDelete.class); protected void handleSoftDelete(BooleanBuilder builder) {
if (softDelete != null && softDelete.value()) { Class<T> entityClass = getEntityClass();
Path<?> deletedPath = EntityPathResolver.getPath(entityPath, "deleted"); LogicDelete softDelete = entityClass.getAnnotation(LogicDelete.class);
if (deletedPath instanceof BooleanPath) { if (softDelete != null && softDelete.value()) {
builder.and(((BooleanPath) deletedPath).eq(false)); Path<?> deletedPath = EntityPathResolver.getPath(entityPath, "deleted");
} if (deletedPath instanceof BooleanPath) {
} builder.and(((BooleanPath) deletedPath).eq(false));
} }
} }
return repository.findAll(builder, createPageRequest(query)); }
protected Sort createSort(BaseQuery query) {
return query != null && StringUtils.hasText(query.getSortField()) ?
Sort.by(Sort.Direction.fromString(query.getSortOrder()), query.getSortField()) :
Sort.by(Sort.Direction.DESC, "createTime");
} }
private void buildQueryPredicate(BaseQuery query, BooleanBuilder builder) { private void buildQueryPredicate(BaseQuery query, BooleanBuilder builder) {
@ -271,69 +295,44 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
} }
@Override @Override
public T create(T entity) { @Transactional(readOnly = false)
return repository.save(entity); public RESP create(REQ request) {
} T entity = conversionService.toEntity(request, getEntityClass());
T savedEntity = createEntity(entity);
@Transactional return conversionService.toResponse(savedEntity);
@Override
public T update(T entity) {
// 先查询最新版本
T currentEntity = findById(entity.getId());
// 版本检查
currentEntity.checkVersion(entity.getVersion());
return repository.save(entity);
} }
@Override @Override
@Transactional(readOnly = false)
public RESP update(ID id, REQ request) {
T entity = findEntityById(id);
conversionService.updateEntity(entity, request);
T updatedEntity = updateEntity(entity);
return conversionService.toResponse(updatedEntity);
}
@Override
@Transactional(readOnly = false)
public void delete(ID id) { public void delete(ID id) {
repository.deleteById(id); repository.deleteById(id);
} }
@Override @Override
public T findById(ID id) { public RESP findById(ID id) {
return repository.findById(id) T entity = findEntityById(id);
.orElseThrow(() -> new EntityNotFoundException(id)); return conversionService.toResponse(entity);
} }
@Override @Override
public List<T> findAll() { public List<RESP> findAll() {
return repository.findAll(); List<T> entities = repository.findAll();
return conversionService.toResponseList(entities);
} }
@Override @Transactional(
public List<T> findAll(BaseQuery query) { readOnly = false,
BooleanBuilder builder = new BooleanBuilder().and(Expressions.asBoolean(true).isTrue()); propagation = Propagation.REQUIRES_NEW
// 添加查询条件 )
if (query != null) {
buildQueryPredicate(query, builder);
}
// 处理软删除
if (query == null || query.getDeleted() == null) {
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class);
if (genericTypes != null && genericTypes.length > 0) {
Class<T> entityClass = (Class<T>) genericTypes[0];
LogicDelete softDelete = entityClass.getAnnotation(LogicDelete.class);
if (softDelete != null && softDelete.value()) {
Path<?> deletedPath = EntityPathResolver.getPath(entityPath, "deleted");
if (deletedPath instanceof BooleanPath) {
builder.and(((BooleanPath) deletedPath).eq(false));
}
}
}
}
// 获取排序信息
Sort sort = query != null && StringUtils.hasText(query.getSortField()) ?
Sort.by(Sort.Direction.fromString(query.getSortOrder()), query.getSortField()) :
Sort.by(Sort.Direction.DESC, "createTime");
// 执行查询并返回结果
Iterable<T> iterable = repository.findAll(builder, sort);
List<T> result = new ArrayList<>();
iterable.forEach(result::add);
return result;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override @Override
public void batchProcess(List<T> entities) { public void batchProcess(List<T> entities) {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
@ -368,19 +367,19 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
}); });
} }
@Transactional @Transactional(readOnly = false)
@Retryable( @Retryable(
value = {OptimisticLockException.class}, value = {OptimisticLockException.class},
maxAttempts = 3, maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2) backoff = @Backoff(delay = 1000, multiplier = 2)
) )
@Override @Override
public T updateWithRetry(T entity) { public RESP updateWithRetry(ID id, REQ request) {
try { try {
return update(entity); return update(id, request);
} catch (OptimisticLockException e) { } catch (OptimisticLockException e) {
// 重试前先刷新实体 // 重试前先刷新实体
entityManager.refresh(entity); entityManager.refresh(findEntityById(id));
throw e; // 抛出异常触发重试 throw e; // 抛出异常触发重试
} }
} }
@ -400,4 +399,25 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
} }
throw new IllegalStateException("Could not resolve entity class"); throw new IllegalStateException("Could not resolve entity class");
} }
// 内部实体操作方法
@Override
public T findEntityById(ID id) {
return repository.findById(id)
.orElseThrow(() -> new EntityNotFoundException(getEntityClass().getSimpleName(), id));
}
@Override
@Transactional(readOnly = false)
public T createEntity(T entity) {
return repository.save(entity);
}
@Override
@Transactional(readOnly = false)
public T updateEntity(T entity) {
T currentEntity = findEntityById(entity.getId());
currentEntity.checkVersion(entity.getVersion());
return repository.save(entity);
}
} }

View File

@ -1,18 +1,18 @@
package com.qqchen.deploy.backend.service; //package com.qqchen.deploy.backend.service;
//
//
import com.qqchen.deploy.backend.framework.service.IBaseService; //import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.entity.Department; //import com.qqchen.deploy.backend.entity.Department;
//
import java.util.List; //import java.util.List;
//
public interface IDepartmentService extends IBaseService<Department, Long> { //public interface IDepartmentService extends IBaseService<Department, Long> {
//
List<Department> getTree(); // List<Department> getTree();
//
void validateCode(String code); // void validateCode(String code);
//
void validateName(String name); // void validateName(String name);
//
Integer getNextSort(Long parentId); // Integer getNextSort(Long parentId);
} //}

View File

@ -1,27 +1,27 @@
package com.qqchen.deploy.backend.service; //package com.qqchen.deploy.backend.service;
//
//
import com.qqchen.deploy.backend.framework.service.IBaseService; //import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.entity.JenkinsConfig; //import com.qqchen.deploy.backend.entity.JenkinsConfig;
//
public interface IJenkinsService extends IBaseService<JenkinsConfig, Long> { //public interface IJenkinsService extends IBaseService<JenkinsConfig, Long> {
// boolean testConnection(JenkinsTestConnectionDTO dto); //// boolean testConnection(JenkinsTestConnectionDTO dto);
//
Long asyncSyncAll(Long jenkinsId); // Long asyncSyncAll(Long jenkinsId);
//
Long asyncSyncView(Long jenkinsId); // Long asyncSyncView(Long jenkinsId);
//
Long asyncSyncJob(Long jenkinsId); // Long asyncSyncJob(Long jenkinsId);
//
Long asyncSyncBuild(Long jenkinsId); // Long asyncSyncBuild(Long jenkinsId);
//
// List<JenkinsSyncHistoryDTO> getSyncHistories(); //// List<JenkinsSyncHistoryDTO> getSyncHistories();
//
// List<ViewResponse> getViews(Long jenkinsId); //// List<ViewResponse> getViews(Long jenkinsId);
//
// List<JobResponse> getJobs(Long jenkinsId); //// List<JobResponse> getJobs(Long jenkinsId);
//
// List<BuildResponse> getBuilds(Long jenkinsId, Long jobId); //// List<BuildResponse> getBuilds(Long jenkinsId, Long jobId);
//
// List<JobResponse> getJobsByView(Long jenkinsId, String viewName); //// List<JobResponse> getJobsByView(Long jenkinsId, String viewName);
} //}

View File

@ -1,20 +1,20 @@
package com.qqchen.deploy.backend.service; //package com.qqchen.deploy.backend.service;
//
//
import com.qqchen.deploy.backend.framework.service.IBaseService; //import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.entity.Menu; //import com.qqchen.deploy.backend.entity.Menu;
//
import java.util.List; //import java.util.List;
//
public interface IMenuService extends IBaseService<Menu, Long> { //public interface IMenuService extends IBaseService<Menu, Long> {
//
// List<MenuDTO> getMenuTree(); //// List<MenuDTO> getMenuTree();
//
// List<MenuDTO> getMenuTreeWithoutButtons(); //// List<MenuDTO> getMenuTreeWithoutButtons();
//
// List<MenuDTO> getUserMenus(Long userId); //// List<MenuDTO> getUserMenus(Long userId);
//
List<Menu> getMenusByRoleId(Long roleId); // List<Menu> getMenusByRoleId(Long roleId);
//
void saveRoleMenus(Long roleId, List<Long> menuIds); // void saveRoleMenus(Long roleId, List<Long> menuIds);
} //}

View File

@ -1,46 +1,46 @@
package com.qqchen.deploy.backend.service; //package com.qqchen.deploy.backend.service;
//
//
import com.qqchen.deploy.backend.framework.service.IBaseService; //import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.entity.RepositoryConfig; //import com.qqchen.deploy.backend.entity.RepositoryConfig;
//
import java.util.List; //import java.util.List;
//
public interface IRepositoryService extends IBaseService<RepositoryConfig, Long> { //public interface IRepositoryService extends IBaseService<RepositoryConfig, Long> {
//
// 仓库配置管理 // // 仓库配置管理
List<RepositoryConfig> listConfigs(); // List<RepositoryConfig> listConfigs();
RepositoryConfig createConfig(RepositoryConfig config); // RepositoryConfig createConfig(RepositoryConfig config);
RepositoryConfig updateConfig(Long id, RepositoryConfig config); // RepositoryConfig updateConfig(Long id, RepositoryConfig config);
void deleteConfig(Long id); // void deleteConfig(Long id);
//
// 测试连接 // // 测试连接
boolean testConnection(RepositoryConfig config); // boolean testConnection(RepositoryConfig config);
// boolean testConnection(TestConnectionDTO dto); //// boolean testConnection(TestConnectionDTO dto);
//
// 同步操作 // // 同步操作
void syncAll(Long repositoryId); // void syncAll(Long repositoryId);
void syncGroups(Long repositoryId); // void syncGroups(Long repositoryId);
void syncProjects(Long repositoryId, Long groupId); // void syncProjects(Long repositoryId, Long groupId);
void syncBranches(Long repositoryId, Long projectId); // void syncBranches(Long repositoryId, Long projectId);
//
/** // /**
* 异步同步仓库数据 // * 异步同步仓库数据
* @param repositoryId 仓库ID // * @param repositoryId 仓库ID
* @return 同步历史ID // * @return 同步历史ID
*/ // */
Long asyncSyncAll(Long repositoryId); // Long asyncSyncAll(Long repositoryId);
//
/** // /**
* 获取同步状态 // * 获取同步状态
* @param historyId 同步历史ID // * @param historyId 同步历史ID
* @return 仓库同步状态 // * @return 仓库同步状态
*/ // */
// RepositorySyncStatusDTO getSyncStatus(Long historyId); //// RepositorySyncStatusDTO getSyncStatus(Long historyId);
//
/** // /**
* 获取正在同步的仓库列表 // * 获取正在同步的仓库列表
* @return 正在同步的仓库信息列表 // * @return 正在同步的仓库信息列表
*/ // */
// List<RunningSyncDTO> getRunningSyncs(); //// List<RunningSyncDTO> getRunningSyncs();
} //}

View File

@ -1,18 +1,18 @@
package com.qqchen.deploy.backend.service; //package com.qqchen.deploy.backend.service;
//
//
import com.qqchen.deploy.backend.framework.service.IBaseService; //import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.entity.Role; //import com.qqchen.deploy.backend.entity.Role;
//
import java.util.List; //import java.util.List;
//
public interface IRoleService extends IBaseService<Role, Long> { //public interface IRoleService extends IBaseService<Role, Long> {
//
void validateCode(String code); // void validateCode(String code);
//
void validateName(String name); // void validateName(String name);
//
List<Long> getRoleMenuIds(Long roleId); // List<Long> getRoleMenuIds(Long roleId);
//
void updateRoleMenus(Long roleId, List<Long> menuIds); // void updateRoleMenus(Long roleId, List<Long> menuIds);
} //}

View File

@ -1,21 +1,10 @@
package com.qqchen.deploy.backend.service; package com.qqchen.deploy.backend.service;
import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.entity.Tenant; import com.qqchen.deploy.backend.entity.Tenant;
import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.dto.request.TenantRequest;
import com.qqchen.deploy.backend.dto.response.TenantResponse;
import java.util.List; public interface ITenantService extends IBaseService<Tenant, Long, TenantRequest, TenantResponse> {
// 添加租户特有的业务方法
public interface ITenantService extends IBaseService<Tenant, Long> {
void validateCode(String code);
void validateName(String name);
List<Tenant> findAllEnabled();
boolean existsByCode(String code);
boolean existsByName(String name);
Tenant findByCode(String code);
} }

View File

@ -4,12 +4,12 @@ import com.qqchen.deploy.backend.framework.service.IBaseService;
import com.qqchen.deploy.backend.dto.request.LoginRequest; import com.qqchen.deploy.backend.dto.request.LoginRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse; import com.qqchen.deploy.backend.dto.response.LoginResponse;
import com.qqchen.deploy.backend.entity.User; import com.qqchen.deploy.backend.entity.User;
import com.qqchen.deploy.backend.dto.request.UserRequest;
import com.qqchen.deploy.backend.dto.response.UserResponse;
public interface IUserService extends IBaseService<User, Long> { public interface IUserService extends IBaseService<User, Long, UserRequest, UserResponse> {
User register(User user); LoginResponse login(LoginRequest request);
User findByUsername(String username); UserResponse register(UserRequest request);
boolean checkUsernameExists(String username); boolean checkUsernameExists(String username);
boolean checkEmailExists(String email); boolean checkEmailExists(String email);
LoginResponse login(LoginRequest request);
} }

View File

@ -1,105 +1,105 @@
package com.qqchen.deploy.backend.service.impl; //package com.qqchen.deploy.backend.service.impl;
//
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; //import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.entity.Department; //import com.qqchen.deploy.backend.entity.Department;
import com.qqchen.deploy.backend.repository.IDepartmentRepository; //import com.qqchen.deploy.backend.repository.IDepartmentRepository;
import com.qqchen.deploy.backend.service.IDepartmentService; //import com.qqchen.deploy.backend.service.IDepartmentService;
import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; //import org.springframework.stereotype.Service;
import jakarta.transaction.Transactional; //import jakarta.transaction.Transactional;
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.List; //import java.util.List;
import java.util.Map; //import java.util.Map;
import java.util.stream.Collectors; //import java.util.stream.Collectors;
//
@Service //@Service
@Transactional //@Transactional
public class DepartmentServiceImpl extends BaseServiceImpl<Department, Long> implements IDepartmentService { //public class DepartmentServiceImpl extends BaseServiceImpl<Department, Long> implements IDepartmentService {
//
private final IDepartmentRepository repository; // private final IDepartmentRepository repository;
//
@Autowired // @Autowired
public DepartmentServiceImpl(IDepartmentRepository repository) { // public DepartmentServiceImpl(IDepartmentRepository repository) {
super(repository); // super(repository);
this.repository = repository; // this.repository = repository;
} // }
//
@Override // @Override
public Department create(Department entity) { // public Department create(Department entity) {
validateCode(entity.getCode()); // validateCode(entity.getCode());
validateName(entity.getName()); // validateName(entity.getName());
return repository.save(entity); // return repository.save(entity);
} // }
//
public Department update(Long id, Department entity) { // public Department update(Long id, Department entity) {
Department existing = repository.findById(id) // Department existing = repository.findById(id)
.orElseThrow(() -> new RuntimeException("部门不存在")); // .orElseThrow(() -> new RuntimeException("部门不存在"));
//
entity.setVersion(existing.getVersion()); // entity.setVersion(existing.getVersion());
entity.setId(id); // entity.setId(id);
//
if (!existing.getCode().equals(entity.getCode())) { // if (!existing.getCode().equals(entity.getCode())) {
if (repository.existsByCodeAndDeletedFalse(entity.getCode())) { // if (repository.existsByCodeAndDeletedFalse(entity.getCode())) {
throw new RuntimeException("部门编码已存在"); // throw new RuntimeException("部门编码已存在");
} // }
} // }
//
if (!existing.getName().equals(entity.getName())) { // if (!existing.getName().equals(entity.getName())) {
if (repository.existsByNameAndDeletedFalse(entity.getName())) { // if (repository.existsByNameAndDeletedFalse(entity.getName())) {
throw new RuntimeException("部门名称已存在"); // throw new RuntimeException("部门名称已存在");
} // }
} // }
//
entity.setCreateTime(existing.getCreateTime()); // entity.setCreateTime(existing.getCreateTime());
entity.setCreateBy(existing.getCreateBy()); // entity.setCreateBy(existing.getCreateBy());
entity.setDeleted(existing.getDeleted()); // entity.setDeleted(existing.getDeleted());
//
return repository.save(entity); // return repository.save(entity);
} // }
//
@Override // @Override
public List<Department> getTree() { // public List<Department> getTree() {
List<Department> departments = repository.findByDeletedFalseOrderBySort(); // List<Department> departments = repository.findByDeletedFalseOrderBySort();
return buildTree(departments); // return buildTree(departments);
} // }
//
@Override // @Override
public void validateCode(String code) { // public void validateCode(String code) {
if (repository.existsByCodeAndDeletedFalse(code)) { // if (repository.existsByCodeAndDeletedFalse(code)) {
throw new RuntimeException("部门编码已存在"); // throw new RuntimeException("部门编码已存在");
} // }
} // }
//
@Override // @Override
public void validateName(String name) { // public void validateName(String name) {
if (repository.existsByNameAndDeletedFalse(name)) { // if (repository.existsByNameAndDeletedFalse(name)) {
throw new RuntimeException("部门名称已存在"); // throw new RuntimeException("部门名称已存在");
} // }
} // }
//
@Override // @Override
public Integer getNextSort(Long parentId) { // public Integer getNextSort(Long parentId) {
return repository.findMaxSortByParentId(parentId) + 1; // return repository.findMaxSortByParentId(parentId) + 1;
} // }
//
private List<Department> buildTree(List<Department> departments) { // private List<Department> buildTree(List<Department> departments) {
Map<Long, List<Department>> parentIdMap = departments.stream() // Map<Long, List<Department>> parentIdMap = departments.stream()
.collect(Collectors.groupingBy(d -> d.getParentId() == null ? 0L : d.getParentId())); // .collect(Collectors.groupingBy(d -> d.getParentId() == null ? 0L : d.getParentId()));
//
return buildTreeNodes(0L, parentIdMap); // return buildTreeNodes(0L, parentIdMap);
} // }
//
private List<Department> buildTreeNodes(Long parentId, Map<Long, List<Department>> parentIdMap) { // private List<Department> buildTreeNodes(Long parentId, Map<Long, List<Department>> parentIdMap) {
List<Department> nodes = new ArrayList<>(); // List<Department> nodes = new ArrayList<>();
//
List<Department> children = parentIdMap.get(parentId); // List<Department> children = parentIdMap.get(parentId);
if (children != null) { // if (children != null) {
for (Department child : children) { // for (Department child : children) {
// child.setChildren(buildTreeNodes(child.getId(), parentIdMap)); //// child.setChildren(buildTreeNodes(child.getId(), parentIdMap));
// nodes.add(child); //// nodes.add(child);
} // }
} // }
//
return nodes; // return nodes;
} // }
} //}

View File

@ -1,69 +1,19 @@
package com.qqchen.deploy.backend.service.impl; //package com.qqchen.deploy.backend.service.impl;
//
import com.qqchen.deploy.backend.framework.exception.BusinessException; //import com.qqchen.deploy.backend.entity.Tenant;
import com.qqchen.deploy.backend.framework.enums.ResponseCode; //import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; //import com.qqchen.deploy.backend.repository.TenantRepository;
import com.qqchen.deploy.backend.entity.QTenant; //import com.qqchen.deploy.backend.service.ITenantService;
import com.qqchen.deploy.backend.entity.Tenant; //import com.qqchen.deploy.backend.dto.request.TenantRequest;
import com.qqchen.deploy.backend.repository.ITenantRepository; //import com.qqchen.deploy.backend.dto.response.TenantResponse;
import com.qqchen.deploy.backend.service.ITenantService; //import org.springframework.core.convert.ConversionService;
import jakarta.transaction.Transactional; //import org.springframework.stereotype.Service;
import org.springframework.stereotype.Service; //
//@Service
import java.util.List; //public class TenantServiceImpl extends BaseServiceImpl<Tenant, Long, TenantRequest, TenantResponse>
// implements ITenantService {
@Service //
@Transactional // public TenantServiceImpl(TenantRepository repository, ConversionService conversionService) {
public class TenantServiceImpl extends BaseServiceImpl<Tenant, Long> implements ITenantService { // super(repository, conversionService);
// }
private final ITenantRepository tenantRepository; //}
public TenantServiceImpl(ITenantRepository tenantRepository) {
super(tenantRepository);
this.tenantRepository = tenantRepository;
}
@Override
public List<Tenant> findAllEnabled() {
QTenant tenant = QTenant.tenant;
return (List<Tenant>) tenantRepository.findAll(
tenant.deleted.eq(false)
.and(tenant.enabled.eq(true)),
tenant.id.asc()
);
}
@Override
public void validateCode(String code) {
// if (tenantRepository.existsByCodeAndDeletedFalse(code)) {
// throw new ApiException("租户编码已存在");
// }
}
@Override
public void validateName(String name) {
// if (tenantRepository.existsByNameAndDeletedFalse(name)) {
// throw new ApiException("租户名称已存在");
// }
}
@Override
public boolean existsByCode(String code) {
return tenantRepository.existsByCodeAndDeletedFalse(code);
}
@Override
public boolean existsByName(String name) {
return tenantRepository.existsByNameAndDeletedFalse(name);
}
@Override
public Tenant findByCode(String code) {
QTenant tenant = QTenant.tenant;
return (Tenant) tenantRepository.findOne(
tenant.code.eq(code)
.and(tenant.deleted.eq(false))
).orElseThrow(() -> new BusinessException(ResponseCode.DATA_NOT_FOUND));
}
}

View File

@ -4,23 +4,27 @@ import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException; import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.security.util.JwtTokenUtil; import com.qqchen.deploy.backend.framework.security.util.JwtTokenUtil;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl; import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.framework.converter.ConversionService;
import com.qqchen.deploy.backend.dto.request.LoginRequest; import com.qqchen.deploy.backend.dto.request.LoginRequest;
import com.qqchen.deploy.backend.dto.request.UserRequest;
import com.qqchen.deploy.backend.dto.response.LoginResponse; import com.qqchen.deploy.backend.dto.response.LoginResponse;
import com.qqchen.deploy.backend.dto.response.UserResponse;
import com.qqchen.deploy.backend.entity.User; import com.qqchen.deploy.backend.entity.User;
import com.qqchen.deploy.backend.repository.IUserRepository; import com.qqchen.deploy.backend.repository.IUserRepository;
import com.qqchen.deploy.backend.service.IUserService; import com.qqchen.deploy.backend.service.IUserService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service @Service
@Slf4j @Slf4j
public class UserServiceImpl extends BaseServiceImpl<User, Long> implements IUserService { public class UserServiceImpl extends BaseServiceImpl<User, Long, UserRequest, UserResponse>
implements IUserService {
private final IUserRepository userRepository; private final IUserRepository userRepository;
@ -30,27 +34,24 @@ public class UserServiceImpl extends BaseServiceImpl<User, Long> implements IUse
@Resource @Resource
private JwtTokenUtil jwtTokenUtil; private JwtTokenUtil jwtTokenUtil;
@Autowired public UserServiceImpl(IUserRepository userRepository, ConversionService conversionService) {
public UserServiceImpl(IUserRepository userRepository) { super(userRepository, conversionService);
super(userRepository);
this.userRepository = userRepository; this.userRepository = userRepository;
} }
@Override @Override
public User register(User user) { @Transactional(readOnly = false)
if (checkUsernameExists(user.getUsername())) { public UserResponse register(UserRequest request) {
throw new RuntimeException("用户名已存在"); if (checkUsernameExists(request.getUsername())) {
throw new BusinessException(ResponseCode.USERNAME_EXISTS);
} }
if (checkEmailExists(user.getEmail())) { if (checkEmailExists(request.getEmail())) {
throw new RuntimeException("邮箱已存在"); throw new BusinessException(ResponseCode.EMAIL_EXISTS);
} }
return userRepository.save(user);
}
@Override User user = conversionService.toEntity(request, User.class);
public User findByUsername(String username) { User savedUser = createEntity(user);
// 实现查询逻辑 return conversionService.toResponse(savedUser);
return null;
} }
@Override @Override
@ -63,15 +64,19 @@ public class UserServiceImpl extends BaseServiceImpl<User, Long> implements IUse
return userRepository.existsByEmail(email); return userRepository.existsByEmail(email);
} }
@Override @Override
@Transactional(readOnly = true)
public LoginResponse login(LoginRequest request) { public LoginResponse login(LoginRequest request) {
Authentication authentication = authenticationManager.authenticate( Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()) new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
); );
UserDetails userDetails = (UserDetails) authentication.getPrincipal(); UserDetails userDetails = (UserDetails) authentication.getPrincipal();
String token = jwtTokenUtil.generateToken(userDetails); String token = jwtTokenUtil.generateToken(userDetails);
User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername()).orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername())
.orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
LoginResponse response = new LoginResponse(); LoginResponse response = new LoginResponse();
response.setId(user.getId()); response.setId(user.getId());
response.setUsername(user.getUsername()); response.setUsername(user.getUsername());
@ -79,8 +84,8 @@ public class UserServiceImpl extends BaseServiceImpl<User, Long> implements IUse
response.setEmail(user.getEmail()); response.setEmail(user.getEmail());
response.setPhone(user.getPhone()); response.setPhone(user.getPhone());
response.setToken(token); response.setToken(token);
log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname()); log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
return response; return response;
} }
} }