Springboot / Angular2 - How to handle HTML5 URLs?

I think this is a simple question, but I could not find the answer or at least use the correct terms in the search.

I customize Angular2and Springboottogether. By default Angularwill use paths such as localhost:8080\dashboardand localhost:8080\dashboard\detail.

I would like to avoid using the path as a hash if possible. As Angular documentation states:

The router function provideRouter sets the LocationStrategy property to PathLocationStrategy, which makes it the default strategy. We can switch to HashLocationStrategy with overriding during the boot process, if we prefer it.

And then...

Almost all Angular 2 projects should use the default HTML style. It creates URLs that are easier for users to understand. And it retains the ability to perform server side rendering later.

The problem is that when I try to access localhost:8080\dashboard, Spring will look for some controller mapping to this path, which it will not have.

Whitelabel Error Page
There was an unexpected error (type=Not Found, status=404).
No message available

At first I thought that all my services would be under localhost:8080\apiand all my static under localhost:8080\app. But how can I tell Spring to ignore requests to this path app?

Is there a better solution with Angular2 or Boot?

+13
source share
7 answers

, ViewController Angular Spring .

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ViewController {

@RequestMapping({ "/bikes", "/milages", "/gallery", "/tracks", "/tracks/{id:\\w+}", "/location", "/about", "/tests","/tests/new","/tests/**","/questions","/answers" })
   public String index() {
       return "forward:/index.html";
   }
}

angular2 ( "/bikes", "/milages", "/gallery", "/tracks", "/tracks/{id:\w +}", "/location", "" /about "," /tests "," /tests/new "," /tests/ ** "," /questions "," /answers ") SPA , 404 . !

+27

, 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;
        }
    };
}
+9

Spring ( 1 2) :

src/main/resources/static

static , Spring Boot .

Spring MVC.
- Java Spring.

WebMvcConfigurer addResourceHandlers(). ResourceHandler ResourceHandlerRegistry.
, classpath:/static/ ( , , , ).
PathResourceResolver getResource(String resourcePath, Resource location).
: ( ), . index.html. URL- HTML 5.

Spring 1.X-:

org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter - .
WebMvcConfigurer , , .

:

import java.io.IOException;

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.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.resource.PathResourceResolver;

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {


    @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");
            }
        });
    }
}

Spring 2.X-:

org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter .
WebMvcConfigurer - , - , ( Java 8) .

:

import java.io.IOException;

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;

@Configuration
public class WebMvcConfig 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");
            }
        });
    }
}
+7

, ErrorPageRegistrar .

@Component
public class ErrorPageConfig implements ErrorPageRegistrar {

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/"));
    }

}

index.html.

@Controller
@RequestMapping("/")
public class MainPageController {

    @ResponseStatus(HttpStatus.OK)
    @RequestMapping({ "/" })
    public String forward() {
        return "forward:/";
    }
}
+1

, :

  • TomcatEmbeddedServletContainerFactory bean RewriteValve

      import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;  
      ...
      import org.apache.catalina.valves.rewrite.RewriteValve; 
      ... 
    
      @Bean TomcatEmbeddedServletContainerFactory servletContainerFactory() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        factory.setPort(8080);
        factory.addContextValves(new RewriteValve());
        return factory;
      }
    
  • rewrite.conf WEB-INF . rewrite.conf, angular, angular PathLocationStrategy ( index.html, spring boot -, RewriteCond):

      RewriteCond %{REQUEST_URI} !^.*\.(bmp|css|gif|htc|html?|ico|jpe?g|js|pdf|png|swf|txt|xml|svg|eot|woff|woff2|ttf|map)$
      RewriteRule ^(.*)$ /index.html [L]
    
  • useHash ( false) :

      RouterModule.forRoot(routes)
    

      RouterModule.forRoot(routes, {useHash: false})
0

, Angular, - :

@Controller
public class ForwardController {

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

: fooobar.com/questions/381700/...

My Spring Boot server for Angular is also a gateway server with API calls on /api, in order not to have a login page in front of Angular pages, you can use something like this.

import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

/**
 * This sets up basic authentication for the microservice, it is here to prevent
 * massive screwups, many applications will require more secuity, some will require less
 */

@EnableOAuth2Sso
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .logout().logoutSuccessUrl("/").and()
                .authorizeRequests()
                .antMatchers("/api/**").authenticated()
                .anyRequest().permitAll().and()
                .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}
0
source

redirect all Angular routing using index.html. Including basic href.

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ViewController {

@RequestMapping({ "jsa/customer","jsa/customer/{id}",})
   public String index() {
       return "forward:/index.html";
   }
}

In my case, jsa is the base href.

0
source

Source: https://habr.com/ru/post/1017173/


All Articles