Spring Boot with redirecting with single page angular2
angular, java, spring, spring-boot, spring-mvc
Solution
For every local REST request not starting with /api overwrite and redirect to default webapp/index.html. I plan to serve anything /api to the spring controllers.
Update 15/05/2017
Let me re-phrase your query for other readers. (Correct me, if misunderstood)
Background Using Spring Boot and Serving static resources from classpath
Requirement All `404` non api requests should be redirected to `index.html`.
NON API - means Requests in which URL doesn't start with `/api`. API - 404 should throw `404` as usual.
Sample Response `/api/something` - will throw `404` `/index.html` - will server index.html `/something` - will redirect to `index.html`
My Solution
Let the Spring MVC throw exceptions, if any handler is not available for the given resource.
Add following to `application.properties`
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
Add a `ControllerAdvice` as follows
@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);
}
}
You can customize the error message as you like.
Is there a way to prefix all controllers with api so that I do not have to write api every time.
For this, you can create a `BaseController` and set the RequestMapping path to `/api`
Example
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api")
public abstract class BaseController {}
And extend this `BaseController` and make sure you do not annotate child class with `@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 !!";
}
}
Previous Answer
You can create a `Filter` which redirects to `/index.html` if request path doesn't startsWith `/api`.
// CODE REMOVED. Check Edit History If you want.
Problem
I have a single page Angular app with Spring Boot. It looks like the following: ``` src main java controller HomeController CustomerController OtherController webapp js/angular-files.js index.html ``` Spring boot correctly defaults to webapp folder and serves index.html file. What I am looking to do is: For every local REST request not starting with `/api` overwrite and redirect to default webapp/index.html. I plan to serve anything `/api` to the spring controllers. Is there a way to prefix all controllers with API so that I do not have to write API every time? e.g. @RequestMapping("/api/home") can write shorthand in code @RequestMapping("/home") or ``` @RequestMapping("/api/other-controller/:id") can write shorthand @RequestMapping("/other-controller/:id") ``` I'm looking for every API request, e.g. 1) http://localhost:8080/api/home keep API with API and resolve to correct controller and return JSON, however if someone enters a URL like http:///localhost/some-url or http:///localhost/some-other/123/url then it will serve the index.html page and keep the URL. Alternative ways to do it: try adding #ErrorViewResolver: Springboot/Angular2 - How to handle HTML5 urls?