我知道您可以在SELECT * FROM
(
SELECT productID,
productType,
MIN(ProductSalesdate) as FirstSale,
MAX(ProductSalesdate) as LastSale,
COUNT(productType) AS ProductCount
FROM Product
GROUP BY productID,productType
) t
PIVOT
(
SUM(ProductCount)
FOR productType IN ([Electronic],[books],[Vehicle])
) p
中设置server.contextPath
来更改根上下文。
另外,我可以在Spring Boot的应用程序配置中添加一个额外的上下文,如下例(在Groovy中)中添加" / api"到根上下文的URL映射:
application.properties
我正在尝试使用单独的基本URI" / api"特别是对于Web服务调用,我可以利用它来保证安全性等。但是使用上述方法将意味着可以使用" /"来访问我的任何URI,无论是否为Web服务。或" / api",并没有提供具体的隔离。
是否有人知道使用配置为所有@Bean
ServletRegistrationBean dispatcherServlet() {
ServletRegistrationBean reg = new ServletRegistrationBean(new DispatcherServlet(), "/")
reg.name = "dispatcherServlet"
reg.addInitParameter("contextConfigLocation", "")
reg.addUrlMappings("/api/*")
reg.loadOnStartup = 2
reg
}
}
设置基本路径的更好方法,而无需使用/ api /正式为每个控制器添加前缀?如果我被迫为每个控制器手动添加前缀URI,则可能会错误地省略它并绕过我特定于Web服务的安全措施。
以下是Stack Overflow中对同一类型问题的引用,该问题从未得到完全解答:
答案 0 :(得分:14)
自Spring Boot 1.4.0.RC1(详情见https://github.com/spring-projects/spring-boot/issues/5004)
以来,有一种解决此类问题的新解决方案Shahin ASkari的解决方案会禁用部分自动配置,因此可能会导致其他问题。
以下解决方案采用了他的想法并将其正确地集成到弹簧启动中。对于我的情况,我希望所有RestControllers都具有基本路径api,但仍然使用根路径提供静态内容(f.e. angular webapp)
修改:我在博客文章中对其进行了总结,其版本略有改进,请参阅https://mhdevelopment.wordpress.com/2016/10/03/spring-restcontroller-specific-basepath/
@Configuration
public class WebConfig {
@Bean
public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
return new WebMvcRegistrationsAdapter() {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new RequestMappingHandlerMapping() {
private final static String API_BASE_PATH = "api";
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
Class<?> beanType = method.getDeclaringClass();
RestController restApiController = beanType.getAnnotation(RestController.class);
if (restApiController != null) {
PatternsRequestCondition apiPattern = new PatternsRequestCondition(API_BASE_PATH)
.combine(mapping.getPatternsCondition());
mapping = new RequestMappingInfo(mapping.getName(), apiPattern,
mapping.getMethodsCondition(), mapping.getParamsCondition(),
mapping.getHeadersCondition(), mapping.getConsumesCondition(),
mapping.getProducesCondition(), mapping.getCustomCondition());
}
super.registerHandlerMethod(handler, method, mapping);
}
};
}
};
}
}
答案 1 :(得分:3)
我有同样的担忧,并且由于记录的问题而不是Spring EL选项的粉丝,我希望在控制器中严格控制前缀,但我不想依赖开发人员做正确的事情。
这些天可能有更好的方法,但这就是我所做的。你们有没有看到任何缺点,我仍然在测试任何副作用。
在RequestMappingHandlerMapping中,我可以读取自定义注释的属性,并根据需要修改最终的RequestMappingInfo。以下是一些代码段:
@Configuration
public class MyWebMvcConfigurationSupport extends WebMvcConfigurationSupport {
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return new MyCustomRequestMappingHandlerMapping();
}
}
在MyCustomRequestMappingHandlerMapping中,覆盖registerHandlerMethod:
private class MyCustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
private Logger myLogger = LoggerFactory.getLogger(MyCustomRequestMappingHandlerMapping.class);
public MyCustomRequestMappingHandlerMapping() {
super();
}
@Override
protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
// find the class declaring this method
Class<?> beanType = method.getDeclaringClass();
// check for the My rest controller annotation
MyRestController myRestAnnotation = beanType.getAnnotation(MyRestController.class);
if (myRestAnnotation != null) {
// this is a My annotated rest service, lets modify the URL mapping
PatternsRequestCondition oldPattern = mapping.getPatternsCondition();
// create a pattern such as /api/v${apiVersion}/${resourceName}
String urlPattern = String.format("/api/v%d/%s",
myRestAnnotation.apiVersion(),
myRestAnnotation.resourceName());
// create a new condition
PatternsRequestCondition apiPattern =
new PatternsRequestCondition(urlPattern);
// ask our condition to be the core, but import all settinsg from the old
// pattern
PatternsRequestCondition updatedFinalPattern = apiPattern.combine(oldPattern);
myLogger.info("re-writing mapping for {}, myRestAnnotation={}, original={}, final={}",
beanType, myRestAnnotation, oldPattern, updatedFinalPattern);
mapping = new RequestMappingInfo(
mapping.getName(),
updatedFinalPattern,
mapping.getMethodsCondition(),
mapping.getParamsCondition(),
mapping.getHeadersCondition(),
mapping.getConsumesCondition(),
mapping.getProducesCondition(),
mapping.getCustomCondition()
);
}
super.registerHandlerMethod(handler, method, mapping);
}
}
答案 2 :(得分:3)
稍微不那么冗长的解决方案,它不会复制检查注释的逻辑,只会改变映射路径:
private static final String API_PREFIX = "api";
@Bean
WebMvcRegistrationsAdapter restPrefixAppender() {
return new WebMvcRegistrationsAdapter() {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new RequestMappingHandlerMapping() {
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo mappingForMethod = super.getMappingForMethod(method, handlerType);
if (mappingForMethod != null) {
return RequestMappingInfo.paths(API_PREFIX).build().combine(mappingForMethod);
} else {
return null;
}
}
};
}
};
}
你的错误控制器也将被映射到/ api / error,这会破坏错误处理(DispatcherServlet仍然会将错误重定向到/ error而没有前缀!)。
可能的解决方案是在上面的代码中添加/ api前缀时跳过/错误路径(另外一个&#34;如果&#34;)。
答案 3 :(得分:2)
还可以通过配置WebMVC来达到相同的结果:
@Configuration
public class PluginConfig implements WebMvcConfigurer {
public static final String PREFIX = "/myprefix";
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix(PREFIX, c -> c.isAnnotationPresent(MyCustomAnnotation.class));
}
}
WebMvcConfigurer
类上实施@Configuration
。configurePathMatch
方法。PathMatchConfigurer
做很多有用的事情,例如为满足谓词条件的多个类添加前缀。答案 4 :(得分:2)
github issue是当前接受的解决方案的延续。
在Spring 5.1及更高版本中,您可以实现WebMvcConfigurer
并覆盖如下所示的configurePathMatch
方法
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("/api",
HandlerTypePredicate.forAnnotation(RestController.class));
}
}
现在,所有@RestControllers
的前缀路径都将以/api
作为配置路径。
答案 5 :(得分:1)
有人在Spring MVC Jira中提出了一个问题,并提出了一个很好的解决方案,我现在正在使用它。我们的想法是在每个RestController文件中使用前缀中的Spring Expression Language,并引用Spring Boot application.properties文件中的单个属性。