2

I've done a lot of research about this subject and haven't found a correct or specific answer, so I'm asking it here before opening a jira ticket on the Spring MVC project.

My application is built with Spring MVC (with spring boot) for the backend and with AngularJS 1.x on front end. I also have html5mode activated (so, no # used, just plain url like http://podcast.dk.lan/podcasts/123/items/456/player).

I have one @Controller route in the back-end redirecting the "/" request to my index.html. All the others routes are handled by @RestController and works with JSON (on "/api" or "/system").

I've searched for the right way to map all the AngularJS routes to the index.html of my application without breaking the other parts of the back-end resolvers (resource for example).

I've tried the following elements :

@Controller
public class HomeController {   
    @RequestMapping(value = "/{.*}")
    private String home() {
    return "forward:/";
    }
}

It's not working because, if I try to access directly to a nested url on the front-end (like /podcasts/1/items/1 ), the url is not caught by the request mapping regex.

@Controller
public class HomeController {   
    @RequestMapping(value = "/**/{.*}")
    private String home() {
    return "forward:/";
    }
}

This configuration lead to a StackOverFlow error because the url will redirect to itself...

Recently, in a really good tutorial about Spring-Security and AngularJS, they used the following pattern:

@Controller
public class HomeController {   
@RequestMapping(value = "/{[path:[^\\.]*}")
    private String home() {
    return "forward:/";
    }
}

This pattern excludes all resources (css and js) by excluding any url with a . (dot) in the url. Unfortunately it's not working with nested routes... returning a 404 error.

So, my app backend is now linked to my route front-end, because I have to hard-code the AngularJS route use in the front-end to the request mapping value :

@Controller
public class HomeController {

    @RequestMapping(value = {"", "items", "podcasts", "podcasts/**", "player", "podcast-creation", "download", "stats"})
    private String home() {
        return "forward:/";
    }
}

I think (and I hope) there is a better solution to redirect all "not already mapped url backend mapping" to a specific method like this.

All the code of my project is hosted on github (if you want to see more code) at davinkevin/Podcast-Server

Thanks for your help

10
  • Angular route should be mapped only on client side. On backend you should map only the entry point page. As a Single Page Application, the rest of the routing is managed on the client side. Commented May 14, 2015 at 21:44
  • Drop your controllers. Add 2 view controllers the first for / to index.html, and /** for the forward. View controllers will be processed after all your other controllers (lowest precedence). Commented May 14, 2015 at 21:53
  • @tarini : The problem I talk about is linked to the activated HTML5Mode in angular, creating url without any hashbang. This lead specific route (other than simple "/") to be interpreted by the backend system if nothing is done. Commented May 14, 2015 at 23:16
  • @M.Deinum : Could you show me an example ? You talk about view controllers defined in the class who extends WebMvcConfigurerAdapter ? Commented May 14, 2015 at 23:21
  • Override the method addViewControllers and create 2 view controllers instead of trying to add your own. Mapping the / before /** should work or just create a /** that redirects everything to the index.html file. Commented May 15, 2015 at 4:54

1 Answer 1

1

I don't know if this is the best solution or not, but it is very simple and worked for us and I believe it should be able to handle your case.

The main goal here is to make the backend forward all requests that are supposed to be resolved by the angular routes (in other words, no real resource URIs in the backend) to the root /, so when the browser loads the index and angular app again, angular can resolve the route on the client side. If you have a well-known and reserved prefix for all angular routes (ie: /fe [short for frontend]), you can use a request mapping pattern that is like /fe/** that returns forward:/.

You just need to make sure that all your angular routes start with /fe/ and there are no static resources in an fe folder or no other request mappings that start with this prefix.

@Controller
public class HomeController { 
    @RequestMapping(value = "/fe/**")
    public String redirect() {
        return "forward:/";
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.