带有 Spring Boot 的 JSON 和 HTML 控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27278791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:39:57  来源:igfitidea点击:

Controller for JSON and HTML with Spring Boot

jsonspringspring-mvcspring-boot

提问by John

I am writing an application where among other things I need to do CRUD operations with certain objects. I need to be able to serve both HTML pages for human users, and JSON for other applications. Right now my URLs look like this for "Read":

我正在编写一个应用程序,其中我需要对某些对象进行 CRUD 操作。我需要能够为人类用户提供 HTML 页面,并为其他应用程序提供 JSON。现在,我的“阅读”网址如下所示:

GET  /foo/{id}      -> Serves HTML
GET  /rest/foo/{id} -> Serves JSON
etc.

This seems a little redundant. I would rather have something like this:

这似乎有点多余。我宁愿有这样的事情:

GET /foo/{id}.html OR /foo/{id} -> Serves HTML
GET /foo/{id}.json              -> Serves JSON

Can Spring Boot do this? If so, how?

Spring Boot 可以做到这一点吗?如果是这样,如何?

I know how to return JSON:

我知道如何返回 JSON:

@RequestMapping(value = "/foo/{id}", method = RequestMethod.GET, produces = "application/json")
public Object fetch(@PathVariable Long id) {
    return ...;
}

I also know how to return HTML:

我也知道如何返回 HTML:

@RequestMapping("/app/{page}.html")
String index(@PathVariable String page) {
    if(page == null || page.equals(""))
        page = "index";
    return page;
}

But I'm not sure how to have a controller do one or the other based on the request.

但我不确定如何让控制器根据请求做一个或另一个。

回答by Maciej Walkowiak

It's a default behavior for Spring Boot. The only thing is that you have to mark one of @RequestMappingto produce JSON. Example:

这是 Spring Boot 的默认行为。唯一的问题是您必须标记其中之一@RequestMapping才能生成 JSON。例子:

@Controller
class HelloController {

    // call http://<host>/hello.json
    @RequestMapping(value = "/hello", method = RequestMethod.GET, produces = "application/json")
    @ResponseBody
    public MyObject helloRest() {
        return new MyObject("hello world");
    }

    // call http://<host>/hello.html or just http://<host>/hello 
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String helloHtml(Model model) {
        model.addAttribute("myObject", new MyObject("helloWorld"));
        return "myView";
    }
}

Read more at: http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvcand http://spring.io/blog/2013/06/03/content-negotiation-using-views

阅读更多信息:http: //spring.io/blog/2013/05/11/content-negotiation-using-spring-mvchttp://spring.io/blog/2013/06/03/content-negotiation-使用视图

回答by Ivan Ursul

Actually, you are mixing rest web service with html pages, it's a bad practice. If you want to build something really great, here is my advice. Write only CRUD operations in your controllers and all html/css/js keep in some static folder and when you will want to see ui part - just call that static index.html file You can read more about that here - http://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot

实际上,您正在将休息 Web 服务与 html 页面混合在一起,这是一种不好的做法。如果你想建立一些真正伟大的东西,这是我的建议。在您的控制器中只编写 CRUD 操作,所有 html/css/js 都保存在某个静态文件夹中,当您想要查看 ui 部分时 - 只需调用该静态 index.html 文件您可以在此处阅读更多相关信息 - http://spring .io/blog/2013/12/19/serving-static-web-content-with-spring-boot

But if you really want to do things as it is now, here is the solution:

但如果你真的想按照现在的方式做事,这里是解决方案:

@RequestMapping(value = "/foo/{id}", method = RequestMethod.GET)
public Object serve(final HttpServletRequest req, final HttpServletResponse resp, @PathVariable final Long id) {
    String header = req.getHeader("Accept");

    // If Accept header will be text/html - then we are forwarding to jsp page.
    if(header.equals("text/html")) {
        req.getRequestDispatcher("login.jsp").forward(req, resp);
    }

    // In other cases we are returning json and setting appropriate headers.
    resp.setHeader("Content-Type", "application/json");
    Object object = "Some string";

    return object;
}