弹簧启动与重定向单页angular2

Rob*_*_UK 16 java spring spring-mvc spring-boot angular

我有一个带弹簧靴的单页角度应用程序.它看起来如下

src
  main
  java
    controller
       HomeController
       CustomerController
       OtherController
  webapp
    js/angular-files.js
    index.html
Run Code Online (Sandbox Code Playgroud)

Spring启动正确默认为webapp文件夹并提供index.html文件.

我要做的是

1) 对于每个本地REST请求,以/ api覆盖开头并重定向到默认的webapp/index.html.我打算为弹簧控制器提供任何/ api服务.

2)有没有办法为所有控制器添加api前缀,这样我就不必每次都写api.

例如

@RequestMapping("/api/home") can write shorthand in code  @RequestMapping("/home")
Run Code Online (Sandbox Code Playgroud)

要么

@RequestMapping("/api/other-controller/:id") can write shorthand  @RequestMapping("/other-controller/:id")
Run Code Online (Sandbox Code Playgroud)

编辑.. 更多注释以上解释更好

我正在寻找每个api请求,例如1) http:// localhost:8080/api/home使用api保持api并解决纠正控制器并返回json.

但是,如果有人输入URL,如http:/// localhost/some-urlhttp:/// localhost/some-other/123/url 那么它将提供index.html页面并保留URL.

在此输入图像描述

替代方法 - 尝试添加#ErrorViewResolver Springboot/Angular2 - 如何处理HTML5网址?

Hyp*_*cle 21

如果您厌倦了尝试通过遵循许多相互矛盾的解决方案来解决此问题,请看这里!

经过数小时努力,尝试遵循数十个堆栈溢出和博客文章中的所有分散建议,我终于找到了最小的PURE spring boot + angular 6应用程序,可在非根页面刷新后始终重定向到index.html。维护所有REST API端点路径。不@EnableWebMvc,不@ControllerAdvice,不更改application.properties,不进行自定义ResourceHandlerRegistry修改,只是简单:

非常重要的先决条件

*必须*包括输出ng buildSpring的resources/static文件夹中。您可以通过来完成此操作maven-resources-plugin。在这里学习:使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

推理

  • resources/static在构建时将ng-build的输出包含进来,可以使spring view redirects("forward:/index.html")成功。spring似乎无法重定向到resources文件夹之外的任何内容,因此,如果您尝试访问站点根目录下的页面,则它将无法正常工作。
  • 使用默认功能(即,没有添加@EnableWebMvc或更改application.properties),导航到/自动提供index.html(如果它已包含在resources/static文件夹中),因此无需在其中进行更改。
  • 使用默认功能(如上所述),spring boot应用程序中遇到的任何错误都会路由到/error并实现ErrorController该行为,从而覆盖该行为(您猜到了),index.html从而可以Angular接管路由。

备注

  • ErrorController 没有任何名为 getErrorPath 的方法,不确定您指的是哪个错误控制器 (3认同)
  • 你是神吗?哇...我花了这么多时间!非常感谢兄弟! (2认同)
  • 只是他的仆人 :-) 很高兴回答对您有所帮助。 (2认同)
  • 如果您查看控制台,您会注意到每个页面请求都有一个错误响应代码,解决方案是将“@ResponseStatus(HttpStatus.OK)”添加到“error()”方法。保重,兄弟。:) (2认同)

ans*_*nsh 19

对于每个本地REST请求,不以/ api覆盖开头并重定向到默认的webapp/index.html.我打算为弹簧控制器提供任何/ api服务.

更新15/05/2017

让我重新对其他读者的查询进行短语.(纠正我,如果被误解)

背景
使用Spring Boot并从classpath提供静态资源

要求
所有404 非api请求都应重定向到index.html.

NON API - 表示不以URL开头的请求/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
Run Code Online (Sandbox Code Playgroud)

添加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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以根据需要自定义错误消息.

有没有办法为所有控制器添加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 {}
Run Code Online (Sandbox Code Playgroud)

并扩展这一点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 !!";
    }

}
Run Code Online (Sandbox Code Playgroud)

上一个答案

如果请求路径没有启动Filter,您可以创建一个重定向到哪个./index.html/api

// CODE REMOVED. Check Edit History If you want.
Run Code Online (Sandbox Code Playgroud)

  • 这看起来接近我正在寻找的东西。但是它已经停止在 webapp 中提供静态内容了吗?返回 ERR_TOO_MANY_REDIRECTS (2认同)

Edu*_*iek 13

试试这个

@SpringBootApplication
@RestController
class YourSpringBootApp { 

    // Match everything without a suffix (so not a static resource)
    @RequestMapping(value = "/**/{path:[^.]*}")       
    public String redirect() {
        // Forward to home page so that route is preserved.
        return "forward:/";
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我想我做错了什么.现在,我得到的是在我的浏览器中"转发:/"^^ (4认同)
  • 回答@Robbo_UK:约定:所有不包含句点的路径(并且未显式映射)都是Angular路由,并且应该转发到主页.来源https://spring.io/blog/2015/05/13/modularizing-the-client-angular-js-and-spring-security-part-vii (3认同)

小智 12

@Controller
public class RedirectController {
    /*
     * Redirects all routes to FrontEnd except: '/', '/index.html', '/api', '/api/**'
     */
    @RequestMapping(value = "{_:^(?!index\\.html|api).*$}")
    public String redirectApi() {
        return "forward:/";
    }
}
Run Code Online (Sandbox Code Playgroud)


Cha*_*dan 6

Too late on this thread, but thought it might help someone

Tried many solutions, but this looked pretty straight forward and great to me

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");
                    }
                });
    }
}
Run Code Online (Sandbox Code Playgroud)

Credits: https://keepgrowing.in/java/springboot/make-spring-boot-surrender-routing-control-to-angular/