Relib HTTP - TroyHisted/relib GitHub Wiki
HTTP Request mapping and routing module.
Features
- Annotation based URL mapping
- Request parameter to bean conversion
- Supports POJOs and JavaBeans
Example
import javax.servlet.annotation.WebServlet;
import org.relib.http.HandleRequest;
import org.relib.http.Controller;
import org.relib.http.HttpMethod;
import org.relib.http.RequestBean;
import org.relib.http.View;
@WebServlet("/root/*")
public class RootController extends Controller {
/**
* Load the root page.
*
* @return view of the root page
*/
@HandleRequest(value = "/root", method = HttpMethod.GET)
public View home() {
return View.of("/WEB-INF/view/root.jsp").put("person", new Person());
}
/**
* Handles saving the root page.
*
* @param person the person to save
* @return view of the root page containing the updated info or any errors
*/
@HandleRequest(value = "/root", method = HttpMethod.POST)
public View post(@RequestBean Person person) {
person.save();
return View.of("/WEB-INF/view/root.jsp").put("person", person);
}
}
URL mapping
This module is built on top of Servlet technology. As such, a Servlet is required either through web.xml configuration or the more recent WebServlet annotation. Using a wildcard mapping (e.g. /root/*) is recommended to ensure nested paths will resolve to the Servlet.
@WebServlet("/root/*")
Mapped methods are invoked through the handleRequest(req, resp)
method of the RequestHandler
class. The various servlet doGet/doPost/etc... methods must all delegate to handleRequest
. The preferred way to accomplish this is to have the servlet extend the Controller
class which has the delegation already implemented.
import org.relib.http.Controller;
public class RootController extends Controller
HandleRequest
Methods are mapped using the @HandleRequest
annotation. The handler may designate the path (relative to the servlet mapping) using the value attribute. If not specified the path will default to "/".
@HandleRequest("/home")
Additionally, the handler may specify any combination of the optional method
, accept
and contentType
values. Method specifies the HttpMethod
(GET/POST/etc..). Accept specifies the format of data returned by the method (the source of the http request will accept a response in the specified format). Content-Type specifies the format of the data coming into the method (the contents of the request are in the specified format).
@HandleRequest(method=HttpMethod.PUT, accept=MediaType.JSON, contentType=MediaType.JSON)
To determine if a request should be processed by a particular HandleRequest
, first the method is checked, then contentType, accept, and finally the path. This order determines the priority of ambiguous mappings.
Request parsing
The arguments of any HandleRequest
method are built dynamically based on the argument type and special parameter annotations.
By default, HttpServletRequest
and HttpServletResponse
are always available. If you wish to access them from your method simply include them in the method signature.
@HandleRequest
public void doSomething(HttpServletRequest req, HttpServletResponse resp) {
req.getParameter("fieldName");
}
Other arguments may be pre-populated by using the PathParam
, RequestParam
, or BeanParam
annotations.
PathParam
The @PathParam
annotation will populate the argument based on the value from the URL path. To use this, the HandleRequest path must include a portion of that path that is to be treated as a wild card. While not required, the general convention is to wrap the wild card in curly braces.
@HandleRequest("/zip/{zipCode}")
public void handleZip(@PathParam("{zipCode}") String zip) {
// Given a request for domain.com/zip/55555 the zip will be populated with "55555"
}
RequestParam
The @RequestParam
annotation will populate the argument based on the value from a request parameter.
@HandleRequest("/customer")
public void loadCustomer(@RequestParam("customerId") Integer id) {
// Given a request for domain.com/customer?customerId=123 the id will be populated with 123
}
RequestBean
The @RequestBean
annotation will populate the argument by building an object of the argument type and populating it from the request arguments using BeanUtils.
@HandleRequest("/order")
public void savePerson(@RequestBean Person person) {
// Given a request for domain.com/user?name=bob&age=40 the person will be created with a name "bob" and age 40
}
If the parameters for the object have a common prefix you may specify that prefix in the @RequestBean
value to have it ignored when mapping to your object.
@HandleRequest("/transfer")
public void savePerson(@RequestBean("buyer") Person buyer, @RequestBean("seller") Person seller) {
// Given a request for domain.com/transfer?buyerName=jim&buyerAge=29&sellerName=bob&sellerAge=40
// The buyer will be populated with a name "jim" and age 29.
// The seller will be populated with a name "bob" and age 40.
}
Returning a View
The return type and accept
property of the controller method, annotated with @HandleRequest
, is used to control the response behavior.
Forwarding to a JSP
Return an instance of org.relib.http.View
using the viewPath
to specify the location of the jsp file to use.
@HandleRequest(value = "/root", method = HttpMethod.GET)
public View home() {
return View.of("/WEB-INF/view/root.jsp").put("person", new Person());
}
The View
may be constructed using the new
keyword or by using the static of
method.
View homePage = new View("/WEB-INF/view/home.jsp");
View aboutPage = View.of("/WEB-INF/view/about.jsp");
Objects may be added to the view using the put
method. This method returns the view to support method chaining.
View.of("/page.jsp").put("foo", 1).put("bar", 2);
Return void to generate no response.
If you wish to control the response, potentially to return a file instead of a jsp, set the return type of your controller method to void.
@HandleRequest(value = "/download", method = HttpMethod.GET)
public void home(HttpServletResponse response) {
// Code that writes a file directly to the response.
}
Return JSON
Set the accept property of the @HandleRequest
annotation to MediaType.JSON
and have the method return the object that is to be converted. Internally this uses Json.toJson
to handle the object conversion.
@HandleRequest(value = "/person", method = HttpMethod.GET, accept = MediaType.JSON)
public Person home() {
return new Person();
}