web-dev-qa-db-ja.com

AngularJS html5ModeによるSpring Boot

私は自分のWebアプリケーションをスプリングブートで起動します。シンプルなメインクラスを使用して、組み込みTomcatサーバーを起動します。

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

でアクティブ化されるangularjs html5modeを処理できるようにサーバーを構成したい

$locationProvider.html5Mode(true);

他のユーザーからの関連する投稿は、ルートにリダイレクトする必要があることを示しています。 html5モードでは、URLからハッシュバッグが削除されます。ページを更新すると、サーバーはページを見つけられず、ハッシュを処理しません。参照: AngularJS-URLアドレスを変更すると$ routeProviderが機能しないように思われ、404エラーが発生する理由

17
Rudolf Schmidt

私はそれと共存できる解決策を見つけました。

@Controller
public class ViewController {

    @RequestMapping("/")
    public String index() {
        return "index";
    }

    @RequestMapping("/app/**")
    public String app() {
        return "index";
    }
}

Angularjsアプリはサブドメインアプリの下にある必要があります。必要ない場合は、サブドメインアプリにマッピングするapp.subdomain.comなどのサブドメインを作成できます。この構成では、webjar、statisコンテンツなどとの競合はありません。

11
Rudolf Schmidt

このコントローラーを使用してURIをindex.htmlに転送し、AngularJSルートを保持します。ソース https://spring.io/blog/2015/05/13/modularizing-the-client-angular-js-and-spring-security-part-vii

_@Controller
public class ForwardController {

    @RequestMapping(value = "/**/{[path:[^\\.]*}")
    public String redirect() {
        // Forward to home page so that route is preserved.
        return "forward:/";
    }
} 
_

このソリューションでは、ForwardControllerは他のControllerまたはRestControllerで定義されていないパスのみを転送します。それはあなたがすでに持っているかどうかを意味します:

_@RestController
public class OffersController {

    @RequestMapping(value = "api/offers")
    public Page<OfferDTO> getOffers(@RequestParam("page") int page) {
        return offerService.findPaginated(page, 10);
    }
} 
_

両方のコントローラーが正しく機能する-@RequestMapping(value = "api/offers")の前に@RequestMapping(value = "/**/{[path:[^\\.]*}")がチェックされる

23
Eduardo Eljaiek

同じ問題がありました。私の知る限り、html5モードでは、angularjsはハッシュを解決しませんが、入力されたURLまたは追加されたURL throughpushState を使用します。

問題は、PathResourceResolverがディレクトリをマップし、ファイルをマップしないことでした。これは、要求されたファイルをディレクトリから提供することを目的としており、URLを書き換えることを目的としていないためです。アプリの場合、つまり、ブラウザウィンドウを更新するか、URLを http://example.com/mystate のように入力すると、サーバーからの「/ mystate」がクエリされます。春がURLを知らない場合、それらは404を返します。解決策の1つは、可能なすべての状態をindex.htmlにマップします heresource 、ところで、webjarsを見てください-それはですすごい!)。しかし、私の場合、 "/ **"をindex.htmlに安全にマップできるため、解決策はPathResourceResolver#getResourceをオーバーライドすることです。

@Configuration
@EnableConfigurationProperties({ ResourceProperties.class })
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private ResourceProperties resourceProperties = new ResourceProperties();

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        Integer cachePeriod = resourceProperties.getCachePeriod();

        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/static/")
                .setCachePeriod(cachePeriod);

        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/index.html")
                .setCachePeriod(cachePeriod).resourceChain(true)
                .addResolver(new PathResourceResolver() {
                    @Override
                    protected Resource getResource(String resourcePath,
                            Resource location) throws IOException {
                        return location.exists() && location.isReadable() ? location
                                : null;
                    }
                });
    }
}
22
Anton Bessonov

以前のコードを少し調整して、うまくいきました。

// Running with Spring Boot v1.3.0.RELEASE, Spring v4.2.3.RELEASE
@Configuration
@EnableConfigurationProperties({ ResourceProperties.class })
public class WebMvcConfig extends WebMvcConfigurerAdapter {

@Autowired
private ResourceProperties resourceProperties = new ResourceProperties();

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    Integer cachePeriod = resourceProperties.getCachePeriod();

    final String[] staticLocations = resourceProperties.getStaticLocations();
    final String[] indexLocations  = new String[staticLocations.length];
    for (int i = 0; i < staticLocations.length; i++) {
        indexLocations[i] = staticLocations[i] + "index.html";
    }
    registry.addResourceHandler(
            "/**/*.css",
            "/**/*.html",
            "/**/*.js",
            "/**/*.json",
            "/**/*.bmp",
            "/**/*.jpeg",
            "/**/*.jpg",
            "/**/*.png",
            "/**/*.ttf",
            "/**/*.eot",
            "/**/*.svg",
            "/**/*.woff",
            "/**/*.woff2"
            )
            .addResourceLocations(staticLocations)
            .setCachePeriod(cachePeriod);

    registry.addResourceHandler("/**")
            .addResourceLocations(indexLocations)
            .setCachePeriod(cachePeriod)
            .resourceChain(true)
            .addResolver(new PathResourceResolver() {
                @Override
                protected Resource getResource(String resourcePath,
                        Resource location) throws IOException {
                    return location.exists() && location.isReadable() ? location
                            : null;
                }
            });
}

}

4
vlk32

カスタムErrorViewResolverを提供することにより、見つからないすべてのリソースをメインページに転送できます。これを@Configurationクラスに追加するだけです:

@Bean
ErrorViewResolver supportPathBasedLocationStrategyWithoutHashes() {
    return new ErrorViewResolver() {
        @Override
        public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
            return status == HttpStatus.NOT_FOUND
                    ? new ModelAndView("index.html", Collections.<String, Object>emptyMap(), HttpStatus.OK)
                    : null;
        }
    };
}
4
Dmitry Serdiuk

最後に、Angular 5アプリケーションが、spring-boot-starter-Tomcatprovided(埋め込み)として、またはなしで、スプリングブートで動作するようになりました。

/**
 * Needed for html5mode (PathLocationStrategy in Angular). Every path except api/* and resources (css, html, js, woff, etc..)
 * should be redirect to index.html and then should angular managed routes (which could be correct or non existing).
 */
@RestController
@RequestMapping
public class ForwardController {

    @GetMapping(value = "/**/{[path:[^\\.]*}")
    public ModelAndView forward() {
        return new ModelAndView("/index.html");
    }
}
3
Gil-galad

リソースを構成すると同時に、AngularJS Html5モードを有効にして使用したいという同様の問題が発生しました。

私の場合、静的ファイルは/publicルートなので、インデックスアクションで次のリクエストマッピングを使用しましたが、すべて正常に機能します。

@RequestMapping(value = {"", "/", "/{[path:(?!public).*}/**"}, method = GET)
public String indexAction() {
    return "index";
}
0
Omer Arshad

1-最初に新しいコントローラーを作成し、次に単純なコードをコピーして貼り付けます

_@Controller
public class viewController {

 @RequestMapping(value = "/**/{[path:[^\\.]*}")
 public String redirect() {
    // Forward to home page so that route is preserved.
    return "forward:/";
 }

}
_

3- angularアプリから項目の下2を削除します

_$locationProvider.hashPrefix('!');
$urlRouterProvider.otherwise("/");
_

2- angular applicationあなたはアプリルートに$locationProvider.html5Mode(true);を追加する必要があります

3- index.htmlファイルでhttpリクエストの前にベースタグを配置することを忘れないでください

_<head>
<base href="/"> /* Or whatever your base path is */

//call every http request for style and other 
...
</head>
_

それは私にとってはうまくいきます

0

angular Html5Modeを使用しているときに同じ問題が発生しました。私のために働いた解決策は、私のケース "/"で私のインデックスビューへのパスを割り当てるweb.xmlで404のエラーページを構成することでした。

<error-page>
    <error-code>404</error-code>
    <location>/</location>
</error-page>

同様に、あなたは春のブートでエラーページを設定してみることができます。参考までに、このリンクを確認してください。

スプリングブートとカスタム404エラーページ

0
modern