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":
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?
I know how to return 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:
@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.
It's a default behavior for Spring Boot. The only thing is that you have to mark one of @RequestMapping
to produce JSON. Example:
@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-mvc and http://spring.io/blog/2013/06/03/content-negotiation-using-views
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
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;
}