4
votes

Hébergement d'une application monopage avec Spring Boot

J'essaie donc d'héberger une application à page unique avec une API REST normale avec spring.

Cela signifie que toutes les demandes qui vont aux points de terminaison normaux / api / doivent être traitées par le contrôleur respectif et toutes les autres demandes doivent être dirigées vers les ressources dans le dossier / statique / construit

J'ai fait fonctionner cela en attrapant toutes les NoHandlerFoundExceptions et en les redirigeant vers le fichier js ou le fichier html . Et puis utilisé un WebMvcConfigurer pour mapper le contenu statique.

Mais tout cela me semble être un hack, alors y a-t-il une manière moins hacky de le faire?


1 commentaires

Il vous suffit de copier les fichiers frontend construits dans le répertoire Spring Boot static / (vous pouvez utiliser le plugin frontend maven pour automatiser cela). Ensuite, Spring Boot les servira de fichiers statiques, vous n'avez pas à vous soucier de la redirection vers html ou js. Utilisez-vous une URL basée sur le hachage dans votre SPA (so.com / # / route / ...)? Si c'est le cas, vous n'avez plus rien à faire au printemps


3 Réponses :



2
votes

La façon la plus simple de faire fonctionner mes SPA avec une API de backend Spring est d'avoir 2 contrôleurs différents: un pour la page d'index racine du SPA et l'autre contrôleur est utilisé pour gérer divers points de terminaison d'API RESTful:

Ici sont mes deux contrôleurs:

MainController.java

entry: ['./src/main/js/index.js']

MonitoringController.java

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head lang="en">
        <meta charset="UTF-8"/>
        <title>EDP Monitoring Tool</title>
    </head>
    <body>
        <!-- Entry point to our ReactJS single page web application -->
        <div id="root"></div>

        <script type="text/javascript" src="built/bundle.js"></script>
    </body>
</html>

Remarquez comment le contrôleur de point final de l'API utilise l'annotation '@RestConroller' tandis que le contrôleur principal utilise l'annotation '@Conroller'. C'est à cause de la façon dont Thymeleaf utilise son ViewResolver. Voir:

Spring Boot MVC, pas retour de ma vue

Maintenant, allez-y et placez votre page index.html dans src / main / resources / templates / index.html car Spring recherche par défaut vos pages html dans cet emplacement.

Mes pages index.html ressemblent à ceci:

@RestController
@RequestMapping(value = "api")
public class MonitoringEndpoints {

    @GetMapping(path = "/health", produces = "application/hal+json")
    public ResponseEntity<?> checkHealth() throws Exception {
        HealthBean healthBean = new HealthBean();
        healthBean.setStatus("UP");

        return ResponseEntity.ok(healthBean);
    }
}

Je ne sais pas comment vous connectez votre frontend, que ce soit une application ReactJS ou quelque chose du genre mais je crois que cette information vous serait utile. Faites-moi savoir si je peux répondre à des questions supplémentaires pour vous.

De plus, si vous utilisez Webpack, vous pouvez configurer le point d'entrée de vos fichiers JS via le fichier webpack.config.js sous la clé d'entrée comme ceci:

@Controller
public class MainController {

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


0 commentaires

5
votes

Nous avons réussi à faire fonctionner l'application React + ReactRouter en ajoutant le mappage suivant:

@Controller
public class RedirectController {

  @GetMapping(value = {"/{regex:\\w+}", "/**/{regex:\\w+}"})
  public String forward404() {
    return "forward:/";
  }

}

Ceci a été inspiré par https://stackoverflow.com/a/42998817/991894


1 commentaires

Les traits d'union ne sont pas un caractère d'expression régulière \ w mais peuvent être dans un point de terminaison, alors remplacez \\ w par [\\ w-] (expression régulière crochet carré pour capturer le caractère trait d'union supplémentaire). Idem pour la période . mais c'est moins courant en tant que nom de point de terminaison, fait probablement référence à une ressource de fichier statique, donc je ne l'inclurais pas.