我有一个带弹簧靴的单页角应用程序。它看起来像以下
src
main
java
controller
HomeController
CustomerController
OtherController
webapp
js/angular-files.js
index.html
Spring启动正确默认为webapp文件夹并提供index.html文件。
我期待的是
1)对于每个本地REST请求不以/ api覆盖开头并重定向到默认的webapp / index.html。我计划为弹簧控制器提供任何/ api。
2)有没有办法为所有控制器添加前缀 用api这样我每次都不用写api。
e.g。
@RequestMapping("/api/home") can write shorthand in code @RequestMapping("/home")
或
@RequestMapping("/api/other-controller/:id") can write shorthand @RequestMapping("/other-controller/:id")
修改.. 更多注释可以更好地解释
我正在寻找每个api请求 例如 1) http://localhost:8080/api/home保持api与api并解决纠正控制器并返回json。
但是,如果有人输入了http:///localhost/some-url或http:///localhost/some-other/123/url等网址,那么它会提供index.html页面并保留网址。
替代方法 - 尝试添加#ErrorViewResolver Springboot/Angular2 - How to handle HTML5 urls?
答案 0 :(得分:15)
对于每个本地REST请求,不以/ api覆盖开头并重定向到默认的webapp / index.html。我计划为弹簧控制器提供任何/ api。
更新15/05/2017
让我重新对其他读者的查询进行短语。 (纠正我,如果被误解)
<强>背景强>
使用Spring Boot并从类路径中提供静态资源
<强>要求强>
所有404
非api 请求都应重定向到index.html
。
NON API - 表示网址不以/api
开头的请求。
API - 404应像往常一样抛出404
。
示例回复
/api/something
- 会抛出404
/index.html
- 将服务器index.html
/something
- 将重定向到index.html
我的解决方案
如果任何处理程序不可用于给定资源,则让Spring MVC抛出异常。
将以下内容添加到application.properties
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
按如下方式添加ControllerAdvice
@ControllerAdvice
public class RedirectOnResourceNotFoundException {
@ExceptionHandler(value = NoHandlerFoundException.class)
public Object handleStaticResourceNotFound(final NoHandlerFoundException ex, HttpServletRequest req, RedirectAttributes redirectAttributes) {
if (req.getRequestURI().startsWith("/api"))
return this.getApiResourceNotFoundBody(ex, req);
else {
redirectAttributes.addFlashAttribute("errorMessage", "My Custom error message");
return "redirect:/index.html";
}
}
private ResponseEntity<String> getApiResourceNotFoundBody(NoHandlerFoundException ex, HttpServletRequest req) {
return new ResponseEntity<>("Not Found !!", HttpStatus.NOT_FOUND);
}
}
您可以根据需要自定义错误消息。
有没有办法为所有控制器添加api前缀,这样我就不必每次都写api。
为此,您可以创建BaseController
并将RequestMapping路径设置为/api
示例强>
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api")
public abstract class BaseController {}
并扩展此BaseController
并确保不使用@RequestMapping
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FirstTestController extends BaseController {
@RequestMapping(path = "/something")
public String sayHello() {
return "Hello World !!";
}
}
上一个答案
如果请求路径未启动 Filter
,您可以创建/index.html
重定向到/api
。
// CODE REMOVED. Check Edit History If you want.
答案 1 :(得分:6)
几个小时后,试图遵循数十个堆栈溢出和博客文章中的所有分散建议,我终于找到了最小的PURE spring boot + angular 6应用程序,该应用程序始终可以重定向到索引。在非根页面上刷新后html,同时维护所有REST API
端点路径。没有@EnableWebMvc
,没有@ControllerAdvice
,没有对application.properties
进行的更改,没有自定义ResourceHandlerRegistry
的修改,只是简单:
您 *必须* 将ng build
的输出包含到Spring的resources/static
文件夹中。您可以通过maven-resources-plugin
完成此操作。在这里学习:Copying multiple resource directories to independent target directories with maven
@Controller
@SpringBootApplication
public class MyApp implements ErrorController {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
private static final String PATH = "/error";
@RequestMapping(value = PATH)
public String error() {
return "forward:/index.html";
}
@Override
public String getErrorPath() {
return PATH;
}
}
resources/static
中可以使spring view重定向("forward:/index.html"
)成功。看来spring无法重定向到resources文件夹之外的任何内容,因此,如果您尝试访问网站根目录下的页面,它将无法正常工作。@EnableWebMvc
或未更改application.properties
),导航到/
会自动提供index.html(如果它包含在resources/static
中文件夹),因此无需在其中进行更改。/error
并实现ErrorController
,从而将该行为覆盖到-您猜到了-路由到index.html
允许Angular
接管路由。HashLocationStrategy
来解决此问题,因此:https://angular.io/guide/router#which-strategy-is-best 答案 2 :(得分:1)
对我有用的解决方案是覆盖Spring Boot的 BasicErrorController :
@Component
public class CustomErrorController extends BasicErrorController {
public CustomErrorController(ErrorAttributes errorAttributes) {
super(errorAttributes, new ErrorProperties());
}
@RequestMapping(produces = "text/html")
@Override
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
if (status == HttpStatus.NOT_FOUND) {
return new ModelAndView("forward:/");
} else {
return super.errorHtml(request, response);
}
}
}
方法 errorHtml 仅拦截未找到的请求,并且对于api的响应404(未找到)是透明的。
答案 3 :(得分:0)
对于整个应用程序,您可以在application.properties
中添加上下文路径server.contextPath = / API
它会在http://localhost:8080/api/home
之后为每个请求的网址添加“/ api”对于重定向,
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/", "/home");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addViewControllers(registry);
}
将这堆代码放在WebMVCConfig.java
中答案 4 :(得分:0)
在@Configuration bean中,您可以添加ServletRegistrationBean以仅为/ api / * resquest创建spring服务器,然后在Controller中不需要添加它。
@Bean
public ServletRegistrationBean dispatcherRegistration() {
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet());
registration.addUrlMappings("/api/*");
registration.setLoadOnStartup(1);
registration.setName("mvc-dispatcher");
return registration;
}
答案 5 :(得分:0)
@Controller
public class RedirectController {
/*
* Redirects all routes to FrontEnd except: '/', '/index.html', '/api', '/api/**'
*/
@RequestMapping(value = "{_:^(?!index\\.html|api).*$}")
public String redirectApi() {
return "forward:/";
}
}
答案 6 :(得分:0)
对于 Spring Boot 2 + (代码在Kotlin中),最合理的解决方案,恕我直言:
@Component
class ForwardErrorsToIndex : ErrorViewResolver {
override fun resolveErrorView(request: HttpServletRequest?,
status: HttpStatus?,
model: MutableMap<String, Any>?): ModelAndView {
return ModelAndView("forward:/index.html")
}
}
答案 7 :(得分:0)
在该线程上为时已晚,但认为这可能对某人有所帮助
尝试了许多解决方案,但这看起来很简单,对我来说很棒
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver;
import java.io.IOException;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
@Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/index.html");
}
});
}
}
积分:https://keepgrowing.in/java/springboot/make-spring-boot-surrender-routing-control-to-angular/
答案 8 :(得分:-1)
好的,让我们从问题的简单部分开始:
有没有办法用api为所有控制器添加前缀,这样我每次都不必编写api?
答案是肯定的,只需使用“全局”@RequestMapping
注释标记您的控制器,例如:
@RestController
@RequestMapping("/api")
public class ApiController{
@RequestMapping("/hello")
public String hello(){
return "hello simple controller";
}
@RequestMapping("/hello2")
public String hello2(){
return "hello2 simple controller";
}
}
在上面的示例中,您可以使用以下URL调用hello方法:/api/hello
以及使用此网址的第二种方法:/api/hello2
这就是我没有用/api
前缀标记每种方法的方式。
现在,问题的更复杂部分:
如果请求不以/api
前缀开头,是如何实现重定向的?
你可以通过返回Redirect的HTTP状态代码(302)来实现,毕竟,angularJs“本地”说“REST”,因此你不能强迫你使用Java / Spring代码重定向。
然后只返回状态代码为302的HTTP消息,并在angularJS上执行实际的重定向。
例如:
关于AngularJS:
var headers = {'Content-Type':'application/json', 'Accept':'application/json'}
var config = {
method:'GET'
url:'http://localhost:8080/hello',
headers:headers
};
http(config).then(
function onSuccess(response){
if(response.status == 302){
console.log("Redirect");
$location("/")
}
}, function onError(response){
console.log("An error occured while trying to open a new game room...");
});
在春天:
@RestController
@RequestMapping("/api")
public class ApiController{
@RequestMapping("/hello")
public ResponseEntity<String> hello(){
HttpHeaders header = new HttpHeaders();
header.add("Content-Type", "application/json");
return new ResponseEntity<String>("", header, HttpStatus.FOUND);
}
}
当然,您需要将其自定义为您的项目。
答案 9 :(得分:-1)
您需要尝试的是index.html
到src/main/resources/static/
参见示例: https://github.com/reflexdemon/shop/tree/master/src/main/resources/static
在我的package.josn
我尝试将其复制到此位置。
请参阅PackageJSON: https://github.com/reflexdemon/shop/blob/master/package.json#L14