简体   繁体   中英

How to return an HTML page from a RESTful controller in Spring Boot?

I want to return a simple HTML page from a controller, but I get only the name of the file not its content. Why?

This is my controller code:

@RestController
public class HomeController {

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

This is my project structure:

[ 在此处输入图像描述

When using @RestController like this:

@RestController
public class HomeController {

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

This is the same as you do like this in a normal controller:

@Controller
public class HomeController {

    @RequestMapping("/")
    @ResponseBody
    public String welcome() {
        return "login";
    }
}

Using @ResponseBody returns return "login"; as a String object. Any object you return will be attached as payload in the HTTP body as JSON.

This is why you are getting just login in the response.

Follow below steps:

  1. Must put the html files in resources/templates/

  2. Replace the @RestController with @Controller

  3. Remove if you are using any view resolvers.

  4. Your controller method should return file name of view without extension like return "index"

  5. Include the below dependencies:

     <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>`

You can try using ModelAndView :

@RequestMapping("/")
public ModelAndView index () {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("index");
    return modelAndView;
}

You should use login.html . And replace RestController with Controller

Replace @Restcontroller with @controller . @Restcontroller returns only content not html and jsp pages.

The answer from Kukkuz did not work for me until I added in this dependency into the pom file:

<!-- Spring boot Thymeleaf -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

From the guide here .

As well as updating the registry resources as outlined here .

It then started working just fine. If anyone in the future runs into the same issue and following the first answer does not solve your problem, follow these 2 other steps after utilizing the code in @Kukkuz's answer and see if that makes a difference.

I know this is old but maybe it helps someone. To do this in a RestController, return a String that is the actual HTML code, then the browser will know what to display.

I did three things:

  • Put the HTML page in {project.basedir}/resources/static/myPage.html;
  • Switch @RestController to @Controller;
  • This is my controller:
@RequestMapping(method = RequestMethod.GET, value = "/")
public String aName() {
    return "myPage.html";
}

No particular dependency is needed.

You get only the name because you return only the name return "login"; . It's @RestController and this controller returns data rather than a view; because of this, you get only content that you return from method.

If you want to show view with this name you need to use Spring MVC, see this example .

@Controller替换@RestController

I'm not using Thymeleaf and the only way it worked for me was with @Controller in the class and

@RequestMapping(method = RequestMethod.GET, value = "/")
public String index() {
    return "index.html";
}

The String you return here:

 return "login";

Is actually the whole content what you send back to the browser.

If you want to have the content of a file to be sent back, one way is:

  1. Open file
  2. Read contents into String
  3. Return the value

You can go by with this answer on the question Spring boot service to download a file

@Controller
public class HomeController {

    @RequestMapping(method = RequestMethod.GET, value = "/")
    public ModelAndView welcome() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("login.html");
        return modelAndView;
    }
}

This will return the Login.html File. The Login.html should be inside the static Folder.

Note: thymeleaf dependency is not added

@RestController
public class HomeController {

    @RequestMapping(method = RequestMethod.GET, value = "/")
    public String welcome() {
        return "login";
    }
}

This will return the String login

@kukkuz pretty much answered to the question 'why?'. For those who are still looking into 'how', accumulating what others have answered.

Using a RestController:

@RestController
public class MyRestController {
    @RequestMapping("/")
    public ModelAndView welcome() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("login.html");
        return modelAndView;
    }  
}
  • pay attention that view name is: 'login.html' (full file name).
  • also it is important where the file is located, by default login.html must be in resources/static or resources/public

You may set up an application parameter for a default suffix like:

 spring.mvc.view.suffix=.html

in this case view name must be without extension like 'login'.

Some suggested thymeleaf can be used. means you have in your pom.xml dependencies something like this:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
  <version>2.4.4</version>
</dependency>

In that scenario login.html by default must sit in: resources/templates folder, and the call is similar only difference now is in a view name, since .html is used by tymeleaf as a default value.

//  fails by default
//  NO fail if spring mvc view suffix is set in properties e.g.: spring.mvc.view.suffix=.html
//  NO fail if thymeleaf is added, and there is a file login.html in a resources/templates folder.
@RequestMapping("/loginTest")
public ModelAndView loginTest () {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("login");
    return modelAndView;
}

Using a Controller:

@Controller
public class MyController {

  //gets html from a default 'resources/public' or 'resources/static' folder
  @RequestMapping(path="/welcome")
  public String getWelcomePage(){
      return "login.html";
  }

  //gets html from a default 'resources/public' or 'resources/static' folder
  @RequestMapping("/welcome1")
  public ModelAndView getWelcomePageAsModel() {
      ModelAndView modelAndView = new ModelAndView();
      modelAndView.setViewName("login.html");
      return modelAndView;
  }

  //  fails with 404 resource not found by default
  //  NO fail, if spring mvc view suffix is set in properties e.g.: spring.mvc.view.suffix=.html
  //  NO fail, if thymeleaf is added, and there is a file login.html in a resources/templates folder
  @RequestMapping(path="/welcome2")
  public String thisFails(){
      return "login";
  }
}

Methods annotated with @GetMapping in classes annotated with @RestController may return views (JSP,HTML etc) in two ways

@GetMapping("/dummy")
public String renderDummyWebPage() {
    return "dummy.jsp";
}

However, this method has two LIMITATIONS

  1. That JSP Page has to be present in src/main/webapp directory, otherwise if the view is present in sub-directory the return type has to be modified accordingly. For example, if the JSP page is present in src/main/webapp/views directory - it should return views/dummy.jsp as String instead.

  2. If you have already configured ViewResolver of the application returning a simple String will not work and the String will be interpreted as a normal String instead of JSP view name.


To overcome these two limitations, you can return a ModelAndView instead.

@GetMapping("/dummy")
public ModelAndView renderDummyWebPage() {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("dummy");
    return modelAndView;
}

I hope this answer would be helpful, thanks.

Already answered by @kukkuz & @Robby with @RequestMapping annotation but we can also use with @GetMapping annotation.

@GetMapping("/index")
public ModelAndView welcome() {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("index.html");
    return modelAndView;
}

You can specify GET or POST method inside RequestMapping like this:-

@RestController
public class HomeController {

@RequestMapping(value="/", Method="GET")  //or Method="POST"
public String welcome() {
    return "/login";
}
}

Now if you request on this page it will return login.html page

The most correct and modern form is to use IoC to put dependencies into the endpoint method, like the thymeleaf Model instance...

 @Controller 
 public class GreetingController {
        @GetMapping("/greeting") 
        public String greeting(
            @RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
             model.addAttribute("name", name); 
             return "greeting"; 
             // returns the already proccessed model from src/main/resources/templates/greeting.html 
      }
 }

See complete example at: https://spring.io/guides/gs/serving-web-content/

@Controller
public class WebController {
@GetMapping("/")

public String homePage() {
    return "index";
  }
}

I had the same issue in Spring boot 3.0.7 and this worked for me:

Change your controller annotations to @Controller and @RequestMapping . The welcome method should use @GetMapping annotation.

@Controller
@RequestMapping
public class HomeController {

    @GetMapping("/")
    public String welcome() {
        return "login";
    }
}

You can solve this in two ways:

First way: If you wish to keep using REST you have to you a ModelAndView object to render a HTML page. An example is being posted by Happy Nguyen and I am posting it once more here:

@RequestMapping("/")
public ModelAndView index () {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("index");
    return modelAndView;
}

Second Way: If it is not important weather you keep using REST or not, so you can just change the @RestController to @Controller and make sure that you have already added Thymeleaf template engine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM