Spring security 有一个基类代表经过身份验证的 User( org.springframework.security.core.userdetails.User):
对 UserDetailsService 检索的核心用户信息进行建模。
开发人员可以直接使用这个类、子类化它,或者从头开始编写他们自己的 UserDetails 实现。
在互联网上的大多数示例中,例如这里人们通常为持久性创建单独的类,即com.mkyong.users.model.User在示例中。这个类没有扩展spring security的一个,所以现在我们有两个Users,一个是持久化的,一个代表系统中经过认证的User,我们所做的一切都是:
所以,我的问题是,再拥有一个 User 对象有什么意义?扩展 spring security User 并坚持它不是更好吗?使用 hibernate/jpa 注释可能无法实现,因为我们显然不能在 spring 安全代码中放置注释,但是可以通过映射文件来实现。这里的另一个问题是我们不应该从服务中返回休眠实体以避免服务层之外的所有类型的休眠相关问题,所以如果我扩展 spring 用户并使其成为实体,我无论如何都需要某种 POJO从UserDetailsService. 这就是我们需要两个 User 对象的原因吗?
对文档的 Ps 参考表示赞赏
这是来自Mockito单元测试框架的报价:
不要嘲笑值对象
为什么一个人甚至想要这样做?
因为实例化对象太痛苦了!=>无效的原因。如果创建新装置太困难,则表明该代码可能需要进行认真的重构。一种替代方法是为您的值对象创建构建器-有一些用于实现此目的的工具,包括IDE插件,Lombok等。也可以在测试类路径中创建有意义的工厂方法。
还有另一个引用来自这里:
为简单的值对象(无论如何应该是不变的)编写模拟并没有多大意义,只需创建一个实例并使用它即可。创建一个接口/实现对来控制返回哪个时间值是不值得的,只需创建具有适当值的实例并使用它们即可。当类不值得嘲笑时,有两种启发式方法。首先,它只具有访问器或简单的方法来对它所拥有的值起作用,它没有任何有趣的行为。其次,除了VideoImpl或类似的模糊术语之外,您无法想到该类的有意义的名称。
这似乎是愚蠢的值对象仅包含值而仅包含值的正当理由,但是当您有一个ValueObject引用实体和其他值对象时,事情变得更加复杂。
假设我有Person和Pet对象,它们是实体和Relationship(所有者,医生等),是两个人之间的ValueObject,并且RelationshipType也是Value Object。因此,关系基本上是:
class Relationship {
private Person person;
private Pet pet;
private RelationshipType type;
}
Run Code Online (Sandbox Code Playgroud)
现在,假设我有一个谓词类似isOwnerRelationship,isDoctorRelationship的类。基本上谓词很简单
关系-> Relationship.isOwner(); //委托给RelationshipType.isOwner()
现在,我要测试谓词,我有两个选择:
模拟关系
public void testIsOwner() {
Relationship rel = mock(Relationship.class);
when(rel.isOwner()).thenReturn(true);
assertTrue(RelationshipPredicates.isOwner(rel));
}
Run Code Online (Sandbox Code Playgroud)
不要嘲笑关系
public void testIsOwner() {
Person person = PersonBuilder.newPerson();
Pet pet = PetBuilder.newDogPet();
RelationshipType type = RelationshipTypes.ownerType();
Relationship rel = new Relationship(person, pet, type);
assertTrue(RelationshipPredicates.isOwner(rel));
}
Run Code Online (Sandbox Code Playgroud)
当然,该示例过于简化,因为对于一个人,您可能需要提供地址,对于Pet,您可能必须提供BreedType,无论如何,即您可能需要提供的实体和值对象的传递图可能非常庞大。当然,您可以模拟实体,但前提是在关系中您有更多的ValueObjects ValueObjects。即使您有一些精巧的生成器,您也必须提供原始ValueObject的每个部分,即使单元测试仅测试其单个方面。
在谓词测试中,如果谓词在乎调用对象的一种特定方法或它们的组合,那我为什么还要在意完整的对象构造?
还是这样的价值对象不能被视为简单且规则不适用?
我有一个 Spring Web 应用程序。当用户调用保存端点时,系统应该执行许多外部调用来保存多个微服务中的状态。但是,这些步骤相互依赖。换句话说,我有一系列的步骤要执行。序列模式
只是一个一个地调用一组步骤并不是什么大不了的事,我可以为每个步骤创建一个类,然后一个一个地调用它们,在步骤之间进行适当的修改。
但是,每个步骤都可能失败,如果发生,应该正确地报告给用户。这是一个直接解决方案的伪代码:
var response = new Response()
try {
var result1 = step1.execute(args1)
var args2 = process(result1, args1)
var result2 = step2.execute(args2)
...
catch(Step1Exception e) {
response.setIsPartialSuccess(true);
response.setPartialResults(e.getDetails())
}
catch(Step2Exception e) {
response.setIsPartialSuccess(true);
response.setPartialResults(e.getDetails())
}
return response;
Run Code Online (Sandbox Code Playgroud)
每个步骤都可以处理项目列表。有些步骤会一次发送所有项目(要么全部失败,要么都不发送),有些步骤会一一发送(一半可以失败,一半可以通过)。StepException 将包含该信息,即什么通过了,什么失败了。
如您所见,它并不是真正可维护的。在这里使用 Spring Batch 会有点矫枉过正,因为我不是在读和写东西,我不需要任何多线程、作业详细信息或检查点。但是,想法非常相似,我想创建一些构建块并控制流程。
目前我正试图弄清楚 Spring Reactor 是否可以在这里提供帮助(是的,我知道它用于不同的目的),因为它具有带有一些错误处理的流/管道。想象一下,我可以这样写:
var context = new Context(response, args1);
Mono.just(context)
.map(step1::execute)
.onErrorReturn(e -> context.withError(e))
//I assume if error happened before
//steps below are not executed
.map(step2::execute)
.onErrorReturn(e -> context.withError(e))
.block()
return …Run Code Online (Sandbox Code Playgroud) 我无法理解NIO是如何在幕后工作的.这是一个示例代码:
// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port 8000
server.socket().bind(new java.net.InetSocketAddress(host,8000));
// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector,SelectionKey.OP_ACCEPT);
while (true) {
selector.select(); // blocking operation
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey selKey = (SelectionKey) it.next();
// THE MOST INTRIGUING PART HERE!!!
if (selKey.isAcceptable()) {
ServerSocketChannel ssChannel = (ServerSocketChannel) selKey.channel();
SocketChannel sc = ssChannel.accept();
}
it.remove();
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我有几个问题:
我正在使用h2嵌入式数据库,其定义如下:
<jdbc:embedded-database id="embeddedDatasource" type="h2"/>
Run Code Online (Sandbox Code Playgroud)
我有两个测试:
@RunWith(SpringJunit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("classpath:h2-context.xml")
class Test1 {...}
@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration("classpath:h2-context.xml")
class Test2 {...}
Run Code Online (Sandbox Code Playgroud)
执行完所有测试后,我确实在日志中看到:
* Closing org.springframework.context.support.GenericApplicationContext
* Closing org.springframework.web.context.support.GenericWebApplicationContext
* Closing JPA EntitiManagerFactory for Persistance unit ...
* Closing JPA EntitiManagerFactory for Persistance unit ...
Run Code Online (Sandbox Code Playgroud)
因此,在执行完所有测试之后,将为每个上下文关闭实体管理器。我知道spring会缓存上下文文件,所以我猜H2 bean在两个测试之间共享。
问题是:有时我会收到奇怪的异常,例如:
H2EmbeddedDatabaseConfigurer: Could not shutdown embedded database
jrg.h2.jdbc.JDBCSQLException: The database has been closed [90098-179]
Run Code Online (Sandbox Code Playgroud)
我该如何解决?
到目前为止,这是我发现的内容: Spring的嵌入式H2数据源和DB_CLOSE_ON_EXIT
java ×5
spring ×2
h2 ×1
hibernate ×1
jpa ×1
mocking ×1
mockito ×1
nio ×1
nonblocking ×1
sockets ×1
spring-batch ×1
spring-test ×1
unit-testing ×1
workflow ×1