我正在尝试制作一个发布CardRequestResource的表单:
public class CardRequestResource extends ResourceSupport{
private Long cardRequestId;
private String deliveryMethod;
private String address;
private boolean isHomeDelivery;
private String requestDate;
private String expectedDate;
private String comments;
private Long statusId;
private PersonResource person;
//Getters and Setters
}
Run Code Online (Sandbox Code Playgroud)
在我的控制器中,我首先加载JSP并将一个空的CardRequestResource添加到ModelMap:
@RequestMapping(value = { "", "/approval" }, method = RequestMethod.GET)
public String getApproval(ModelMap map) {
map.put("cardRequestResource", new CardRequestResource());
return "cardoffice/approval";
}
Run Code Online (Sandbox Code Playgroud)
我的JSP使用cardRequestResource模型属性构建表单:
<form:form id="detailForm" name="detailForm" modelAttribute="cardRequestResource">
<form:input path="statusId" type="hidden" id="statusId" name="statusId" />
<form:textarea path="comments" name="comments" id="commentTextarea" rows="7" cols="81" style="font-style: normal;"/>
</form:form>
Run Code Online (Sandbox Code Playgroud)
Javascript函数进行AJAX调用以填充表单值:
function …Run Code Online (Sandbox Code Playgroud) 我已经熟悉Spring @Value注释的基本行为,将字段设置为项目属性的值,如下所示:
项目的属性文件
foo.bar=value
Run Code Online (Sandbox Code Playgroud)
项目的配置类
@Configuration
public class MyConfig {
@Value("${foo.bar}")
private String myValue;
}
Run Code Online (Sandbox Code Playgroud)
但是,我正在尝试使用条件配置创建一个SpringBoot启动项目,并希望将属性名称标准化为有用的东西,例如"com.mycompany.propertygroup.propertyname",但为了简化转换并鼓励采用,我想支持一段时间内的旧属性名称,因此想知道是否有某种方法允许多个属性名称设置相同的字段?例如:
我的理论初学者的配置
@Configuration
public class MyConfig {
@Value("${com.mycompany.propertygroup.propertyname}" || "${oldconvention.property}")
private String myValue;
}
Run Code Online (Sandbox Code Playgroud)
项目A的财产
oldconvention.property=value
Run Code Online (Sandbox Code Playgroud)
项目B的财产
com.mycompany.propertygroup.propertyname=value
Run Code Online (Sandbox Code Playgroud)
我似乎无法找到任何关于这是否可行的文件或SO答案以及如何实现它......所以我想知道是否可能,或者如果不可能,是否有替代方案@Value注释可以用来达到同样的效果?
编辑澄清: 我不想跟踪多个值,所以我并不需要如何让多个值指令......目标是合并成一个单一的值是可以有多个名称.在实践中,每个项目使用启动器只会有一个名称值...只有在极少数情况下,当有人忘记删除旧属性时才会使用每个属性名称(并且它可能具有相同的值) ).在这种情况下,新的公约名称价值只能是一次使用.
虽然提供的SpEL表达式答案在两个属性都存在时都有效,但只有一个属性名称存在时才能加载应用程序上下文.例:
更新的配置类
@Value("#{'${com.mycompany.propertygroup.propertyname}' != null ? '${com.mycompany.propertygroup.propertyname}' : '${oldconvention.propertyname}'}"
private String myProperty;
Run Code Online (Sandbox Code Playgroud)
更新的属性文件
com.mycompany.propertygroup.propertyname=somevalue
Run Code Online (Sandbox Code Playgroud)
错误
Caused by: java.lang.IllegalArgumentException:
Could not resolve placeholder 'oldconvention.propertyname' in value
"#{'${com.mycompany.propertygroup.propertyname}' != null ? '${com.mycompany.propertygroup.propertyname}' : '${oldconvention.propertyname}'}"
Run Code Online (Sandbox Code Playgroud)
要求两个属性名称都存在失败的目的,即允许实现项目使用旧约定或新约定配置此启动器...
另一个更新......
我一直在玩SpEL表达式,并且当属性存在时我已经进行了条件检查,但是当它没有时,我在事后解决了属性问题.我认为问题是因为属性默认值和复杂的SpEL表达式不能很好地结合在一起. …
我有一个具有布尔值的实体,该值作为“Y”或“N”字符持久存在于数据库中:
@Data
@Entity
@Table(name = "MYOBJECT", schema = "MYSCHEMA")
@EqualsAndHashCode(of = "id")
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class MyObject {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MYOBJECT_SEQ")
@SequenceGenerator(name = "MYOBJECT_SEQ", sequenceName = "MYSCHEMA.MYOBJECT_SEQ")
private Long id;
@NotEmpty(message = "Name may not be empty")
@SafeHtml(whitelistType = WhiteListType.NONE, message = "Name may not contain html or javascript")
@Column(name = "NAME", nullable = false, length = 60)
private String name;
// Other fields...
@Type(type = "yes_no")
@Column(name = "ACTIVE", length = 1, nullable = …Run Code Online (Sandbox Code Playgroud) TL; DR:经过多次试验和错误,似乎问题与Tomcat有关,可能与配置的java版本有关,而不是java语言本身.有关详细信息,请参阅下面的"编辑3".
我一直在使用Java 8流和比较器一段时间,以前从未见过这种类型的行为,所以我要求好奇,看看是否有人能找到我的流有什么问题.
我正在研究"Java-8-ifying"一个遗留项目,用流替换我们过时的收集处理(我被问到为什么我这样做,简短的回答是我们基本上重写了项目,但只有时间预算才能逐步完成.我正在做第一步 - 更新java版本.围绕集合逻辑有很多混乱的代码,所以"Java-8-ifying"正在用于清理很多代码和使事情更容易阅读和维护).目前,我们仍在使用旧的数据类型,因此提到的任何日期都是处理java.util.Date实例而不是新的Java 8类型.
这是ServiceRequest.java中的Comparator(它是一个POJO):
public static final Comparator<ServiceRequest> BY_ACTIVITY_DATE_DESC = Comparator.comparing(
ServiceRequest::getActivityDate, Comparator.nullsLast(Comparator.reverseOrder()));
Run Code Online (Sandbox Code Playgroud)
单元测试时,此比较器按预期工作.具有较晚activityDate的ServiceRequests在结果列表中排在第一位,具有较早activityDate的ServiceRequests位于列表的下方,而具有null activityDate的ServiceRequests位于底部.作为参考,这里是单元测试的完整副本:
@Test
public void testComparator_BY_ACTIVITY_DATE_DESC() {
ServiceRequest olderRequest = new ServiceRequest();
olderRequest.setActivityDate(DateUtil.yesterday());
ServiceRequest newerRequest = new ServiceRequest();
newerRequest.setActivityDate(DateUtil.tomorrow());
ServiceRequest noActivityDateRequest = new ServiceRequest();
List<ServiceRequest> sortedRequests = Arrays.asList(olderRequest, noActivityDateRequest, newerRequest).stream()
.sorted(ServiceRequest.BY_ACTIVITY_DATE_DESC)
.collect(Collectors.toList());
assertEquals(sortedRequests.get(0), newerRequest);
assertEquals(sortedRequests.get(1), olderRequest);
assertEquals(sortedRequests.get(2), noActivityDateRequest);
}
Run Code Online (Sandbox Code Playgroud)
注意:DateUtil是一个遗留实用程序,它为我们的测试目的创建java.util.Date实例.
正如我所料,这项测试总是以绚丽的色彩传递.但是,我有一个控制器,它组装一个开放服务请求列表,并按请求者标识符对它们进行分组,并仅将该用户的最新请求选择到映射中.我试图将此逻辑转换为给定的流:
private Map<Long, ServiceRequestViewBean> ServiceRequestsByUser(List<ServiceRequest> serviceRequests) {
return serviceRequests.stream()
.sorted(ServiceRequest.BY_ACTIVITY_DATE_DESC)
.collect(Collectors.toMap(
serviceRequest -> serviceRequest.getRequester().getId(),
serviceRequest -> new ServiceRequestViewBean(serviceRequest),
(firstServiceRequest, secondServiceRequest) …Run Code Online (Sandbox Code Playgroud) 我正在使用 Rest Assured 为我的 Spring Boot 项目进行控制器测试。我们在序列化对象上使用 Java 8 ZonedDateTime 字段,并使用 Jackson 2 进行序列化。运行项目时,序列化按预期工作,但运行放心测试时,日期未正确序列化。我知道 Rest Assured 使用自己的 ObjectMapper 配置,但我的问题是,无论我做什么,Rest Assured 似乎都会忽略我的 ObjectMapper 配置。
以下是我测试的相关部分:
@RunWith(SpringRunner.class)
@SpringBootTest(classes=MyApplication.class)
@WebAppConfiguration
@Transactional
public class MAppControllerTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@Before
public void setUp() throws Exception {
RestAssured.config = RestAssuredConfig.config().objectMapperConfig(
ObjectMapperConfig.objectMapperConfig().jackson2ObjectMapperFactory(new Jackson2ObjectMapperFactory() {
@SuppressWarnings("rawtypes")
@Override
public ObjectMapper create(Class cls, String charset) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setTimeZone(TimeZone.getTimeZone("America/New_York"));
objectMapperconfigure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, true);
return objectMapper;
}
})
);
mockMvc …Run Code Online (Sandbox Code Playgroud) 我正在尝试制作一个自定义 Spring Boot 启动器,多个项目将使用它来对 Azure AD 进行身份验证。已设置所有 Azure AD 配置,并且使用所有设置硬编码的单个项目也可以与 Azure AD 配合使用。现在我正在尝试将这些设置移动到自定义 Spring Boot 启动器中,以便多个项目可以使用它。它在大多数情况下都有效,除了一件事:移动自定义AADAppRoleStatelessAuthenticationFilter. 如果我将自定义实现 ( CustomAADAppRoleStatelessAuthFilter) 硬编码在实际实现项目中,则一切正常并且仅CustomAADAppRoleStatelessAuthFilter创建,但是一旦我将其移入自定义启动器,我只会得到AADAppRoleStatelessAuthenticationFilter。
请注意,我的CustomAADAppRoleStatelessAuthFilter扩展了启动器的
AADAppRoleStatelessAuthenticationFilter.
AADAppRoleStatelessAuthenticationFilterazure-spring-boot 项目中的自动配置( https://github.com/microsoft/azure-spring-boot/blob/master/azure-spring-boot/src/main/java/com/microsoft/azure/ spring/autoconfigure/aad/AADAuthenticationFilterAutoConfiguration.java ) 是:
@Bean
@ConditionalOnMissingBean(AADAppRoleStatelessAuthenticationFilter.class)
@ConditionalOnProperty(prefix = PROPERTY_PREFIX, value = PROPERTY_SESSION_STATELESS, havingValue = "true")
public AADAppRoleStatelessAuthenticationFilter azureADStatelessAuthFilter(ResourceRetriever resourceRetriever) {
//bean details omitted
}
Run Code Online (Sandbox Code Playgroud)
我应该替换上述内容的自定义自动配置如下:
@Bean
@ConditionalOnMissingBean(AADAppRoleStatelessAuthenticationFilter.class)
@ConditionalOnProperty(prefix = PROPERTY_PREFIX, value = PROPERTY_SESSION_STATELESS, havingValue = "true")
public AADAppRoleStatelessAuthenticationFilter customAADAppRoleStatelessAuthFilter(
ResourceRetriever resourceRetriever) {
return new …Run Code Online (Sandbox Code Playgroud) 我有一个针对自定义 Spring Boot Starter 的 Gradle 多项目构建。按照 Spring Boot Starter 约定,我的类全部位于“自动配置”项目中,并且我有一个单独的“启动器”项目,该项目仅引入使用自动配置所需的依赖项。
多项目构建会生成 2 个不可运行的 jar,其中 1 个用于自动配置子项目,1 个用于启动子项目。我使用此启动器的新项目会拉入启动器 jar,但是当我使用来自传递依赖项的类时,我的项目在类路径上的任何位置都找不到它们。
当我深入研究 starter jar 时,我发现它定义的所有依赖项都是运行时范围的,这可以解释问题。我可以通过将启动器中的所有依赖项设置为“编译”而不是“实现”来“修复”问题,但我的理解是“编译”即将消失,并且“实现”依赖项应该在编译范围内反正。有人可以告诉我可能需要什么额外的配置才能将启动器依赖项定义为“实现”而不将它们在生成的 jar 中定义为“运行时”吗?
我的启动器/自动配置多项目根gradle 文件:
plugins {
id 'org.springframework.boot' version '2.1.4.RELEASE' apply false
id 'io.spring.dependency-management' version '1.0.7.RELEASE' apply false
}
wrapper {
gradleVersion = '5.2.1'
}
repositories {
mavenLocal()
// private repo info omitted
mavenCentral()
jcenter()
}
subprojects {
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'maven-publish'
apply plugin: 'java-library'
group = …Run Code Online (Sandbox Code Playgroud) dependency-management gradle spring-boot spring-boot-starter
java ×4
spring-boot ×4
collectors ×1
default ×1
forms ×1
gradle ×1
hibernate ×1
jackson ×1
java-8 ×1
java-stream ×1
jpa ×1
jquery ×1
lombok ×1
null ×1
properties ×1
rest-assured ×1
sorting ×1
spring ×1
spring-mvc ×1
timezone ×1
tomcat ×1