Can you give me a brief explanation and a sample in using #PathVariable in spring mvc? Please include on how you type the url?
I'm struggling in getting the right url to show the jsp page. Thanks.
suppose you want to write a url to fetch some order, you can say
www.mydomain.com/order/123
where 123 is orderId.
So now the url you will use in spring mvc controller would look like
/order/{orderId}
Now order id can be declared a path variable
#RequestMapping(value = " /order/{orderId}", method=RequestMethod.GET)
public String getOrder(#PathVariable String orderId){
//fetch order
}
if you use url www.mydomain.com/order/123, then orderId variable will be populated by value 123 by spring
Also note that PathVariable differs from requestParam as pathVariable is part of URL.
The same url using request param would look like www.mydomain.com/order?orderId=123
API DOC
Spring Official Reference
Have a look at the below code snippet.
#RequestMapping(value="/Add/{type}")
public ModelAndView addForm(#PathVariable String type) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("addContent");
modelAndView.addObject("typelist", contentPropertyDAO.getType() );
modelAndView.addObject("property", contentPropertyDAO.get(type,0) );
return modelAndView;
}
Hope it helps in constructing your code.
If you have url with path variables, example www.myexampl.com/item/12/update where 12 is the id and create is the variable you want to use for specifying your execution for instance in using a single form to do an update and create, you do this in your controller.
#PostMapping(value = "/item/{id}/{method}")
public String getForm(#PathVariable("id") String itemId ,
#PathVariable("method") String methodCall , Model model){
if(methodCall.equals("create")){
//logic
}
if(methodCall.equals("update")){
//logic
}
return "path to your form";
}
#PathVariable used to fetch the value from URL
for example: To get some question
www.stackoverflow.com/questions/19803731
Here some question id is passed as a parameter in URL
Now to fetch this value in controller all you have to do is just to pass #PathVariable in the method parameter
#RequestMapping(value = " /questions/{questionId}", method=RequestMethod.GET)
public String getQuestion(#PathVariable String questionId){
//return question details
}
Annotation which indicates that a method parameter should be bound to a URI template variable. Supported for RequestMapping annotated handler methods.
#RequestMapping(value = "/download/{documentId}", method = RequestMethod.GET)
public ModelAndView download(#PathVariable int documentId) {
ModelAndView mav = new ModelAndView();
Document document = documentService.fileDownload(documentId);
mav.addObject("downloadDocument", document);
mav.setViewName("download");
return mav;
}
Let us assume you hit a url as www.example.com/test/111 .
Now you have to retrieve value 111 (which is dynamic) to your controller method .At time you ll be using #PathVariable as follows :
#RequestMapping(value = " /test/{testvalue}", method=RequestMethod.GET)
public void test(#PathVariable String testvalue){
//you can use test value here
}
SO the variable value is retrieved from the url
It is one of the annotation used to map/handle dynamic URIs. You can even specify a regular expression for URI dynamic parameter to accept only specific type of input.
For example, if the URL to retrieve a book using a unique number would be:
URL:http://localhost:8080/book/9783827319333
The number denoted at the last of the URL can be fetched using #PathVariable as shown:
#RequestMapping(value="/book/{ISBN}", method= RequestMethod.GET)
public String showBookDetails(#PathVariable("ISBN") String id,
Model model){
model.addAttribute("ISBN", id);
return "bookDetails";
}
In short it is just another was to extract data from HTTP requests in Spring.
have a look at the below code snippet.
#RequestMapping(value = "edit.htm", method = RequestMethod.GET)
public ModelAndView edit(#RequestParam("id") String id) throws Exception {
ModelMap modelMap = new ModelMap();
modelMap.addAttribute("user", userinfoDao.findById(id));
return new ModelAndView("edit", modelMap);
}
If you want the complete project to see how it works then download it from below link:-
UserInfo Project on GitLab
Related
I think the fault comes from ulr introduced in the RedirectView parameter, but I tried different URL's and I can't make it work.
This is my project estructure:
And this is the get method from Spring MVC in controller package
#GetMapping("/planetForm")
#ResponseBody
public RedirectView toPlanetForm(Model model, #RequestParam(value = "idPlanet", required = false) String idPlanet) {
if (idPlanet != null){
Planet planet = planetService.getById(Integer.parseInt(idPlanet));
model.addAttribute("planet", planet);
}
List<Satellite> satellites = satelliteService.findAll();
model.addAttribute("satellites", satellites);
return new RedirectView("./addPlanet");
}
As you can see I am trying to do the RedirectView to the JSP called addPlanet.jsp.
I have also tried this url (among others): "../webapp/WEB-INF/jsp/addPlanet.jsp", I am convinced that it is a rookie nonsense, but I am unable to see the error
I have also tried to create another servlet and retrieve the object I need through the #ModelAtribute, but the object added in the first servlet is lost in the process, this is the code:
#GetMapping("/updatePlanet")
#ResponseBody
String update(Model model, #ModelAttribute("planet") Planet planet){
model.addAttribute("planet",planet);
return "addPlanet";
}
This wat sends the user to the addPlanet.jstl, but the object obtained by this method is an object just created by the constructor with attributes with the value of null or 0
Finally I found the solution, here it is:
#GetMapping("/planetForm/{idPlanet}")
public String toPlanetForm(Model model, #PathVariable(value = "idPlanet", required = false) String idPlanet) {
if (idPlanet != null){
Planet planet = planetService.getById(Integer.parseInt(idPlanet));
model.addAttribute("planet", planet);
}
List<Satellite> satellites = satelliteService.findAll();
model.addAttribute("satellites", satellites);
return "addPlanet";
}
As you can see I had to change the #GetMapping for a new URL, now the function returns a String which is the name of the JSP without extension. In addition to the parameter of the function #RequestParam I have had to change it to#PathVariable, which its value is the same as the mustache expression of #GetMapping
What is the difference between #RequestParam and #PathVariable while handling special characters?
+ was accepted by #RequestParam as space.
In the case of #PathVariable, + was accepted as +.
#PathVariable is to obtain some placeholder from the URI (Spring call it an URI Template)
— see Spring Reference Chapter 16.3.2.2 URI Template Patterns
#RequestParam is to obtain a parameter from the URI as well — see Spring Reference Chapter 16.3.3.3 Binding request parameters to method parameters with #RequestParam
If the URL http://localhost:8080/MyApp/user/1234/invoices?date=12-05-2013 gets the invoices for user 1234 on December 5th, 2013, the controller method would look like:
#RequestMapping(value="/user/{userId}/invoices", method = RequestMethod.GET)
public List<Invoice> listUsersInvoices(
#PathVariable("userId") int user,
#RequestParam(value = "date", required = false) Date dateOrNull) {
...
}
Also, request parameters can be optional, and as of Spring 4.3.3 path variables can be optional as well. Beware though, this might change the URL path hierarchy and introduce request mapping conflicts. For example, would /user/invoices provide the invoices for user null or details about a user with ID "invoices"?
#RequestParam annotation used for accessing the query parameter values from the request. Look at the following request URL:
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
In the above URL request, the values for param1 and param2 can be accessed as below:
public String getDetails(
#RequestParam(value="param1", required=true) String param1,
#RequestParam(value="param2", required=false) String param2){
...
}
The following are the list of parameters supported by the #RequestParam annotation:
defaultValue – This is the default value as a fallback mechanism if request is not having the value or it is empty.
name – Name of the parameter to bind
required – Whether the parameter is mandatory or not. If it is true, failing to send that parameter will fail.
value – This is an alias for the name attribute
#PathVariable
#PathVariable identifies the pattern that is used in the URI for the incoming request. Let’s look at the below request URL:
http://localhost:8080/springmvc/hello/101?param1=10¶m2=20
The above URL request can be written in your Spring MVC as below:
#RequestMapping("/hello/{id}") public String getDetails(#PathVariable(value="id") String id,
#RequestParam(value="param1", required=true) String param1,
#RequestParam(value="param2", required=false) String param2){
.......
}
The #PathVariable annotation has only one attribute value for binding the request URI template. It is allowed to use the multiple #PathVariable annotation in the single method. But, ensure that no more than one method has the same pattern.
Also there is one more interesting annotation:
#MatrixVariable
http://localhost:8080/spring_3_2/matrixvars/stocks;BT.A=276.70,+10.40,+3.91;AZN=236.00,+103.00,+3.29;SBRY=375.50,+7.60,+2.07
And the Controller method for it
#RequestMapping(value = "/{stocks}", method = RequestMethod.GET)
public String showPortfolioValues(#MatrixVariable Map<String, List<String>> matrixVars, Model model) {
logger.info("Storing {} Values which are: {}", new Object[] { matrixVars.size(), matrixVars });
List<List<String>> outlist = map2List(matrixVars);
model.addAttribute("stocks", outlist);
return "stocks";
}
But you must enable:
<mvc:annotation-driven enableMatrixVariables="true" >
#RequestParam is use for query parameter(static values) like: http://localhost:8080/calculation/pow?base=2&ext=4
#PathVariable is use for dynamic values like : http://localhost:8080/calculation/sqrt/8
#RequestMapping(value="/pow", method=RequestMethod.GET)
public int pow(#RequestParam(value="base") int base1, #RequestParam(value="ext") int ext1){
int pow = (int) Math.pow(base1, ext1);
return pow;
}
#RequestMapping("/sqrt/{num}")
public double sqrt(#PathVariable(value="num") int num1){
double sqrtnum=Math.sqrt(num1);
return sqrtnum;
}
1) #RequestParam is used to extract query parameters
http://localhost:3000/api/group/test?id=4
#GetMapping("/group/test")
public ResponseEntity<?> test(#RequestParam Long id) {
System.out.println("This is test");
return ResponseEntity.ok().body(id);
}
while #PathVariable is used to extract data right from the URI:
http://localhost:3000/api/group/test/4
#GetMapping("/group/test/{id}")
public ResponseEntity<?> test(#PathVariable Long id) {
System.out.println("This is test");
return ResponseEntity.ok().body(id);
}
2) #RequestParam is more useful on a traditional web application where data is mostly passed in the query parameters while #PathVariable is more suitable for RESTful web services where URL contains values.
3) #RequestParam annotation can specify default values if a query parameter is not present or empty by using a defaultValue attribute, provided the required attribute is false:
#RestController
#RequestMapping("/home")
public class IndexController {
#RequestMapping(value = "/name")
String getName(#RequestParam(value = "person", defaultValue = "John") String personName) {
return "Required element of request param";
}
}
it may be that the application/x-www-form-urlencoded midia type convert space to +, and the reciever will decode the data by converting the + to space.check the url for more info.http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
#PathVariable - must be placed in the endpoint uri and access the query parameter value from the request
#RequestParam - must be passed as method parameter (optional based on the required property)
http://localhost:8080/employee/call/7865467
#RequestMapping(value=“/call/{callId}", method = RequestMethod.GET)
public List<Calls> getAgentCallById(
#PathVariable(“callId") int callId,
#RequestParam(value = “status", required = false) String callStatus) {
}
http://localhost:8080/app/call/7865467?status=Cancelled
#RequestMapping(value=“/call/{callId}", method = RequestMethod.GET)
public List<Calls> getAgentCallById(
#PathVariable(“callId") int callId,
#RequestParam(value = “status", required = true) String callStatus) {
}
Both the annotations behave exactly in same manner.
Only 2 special characters '!' and '#' are accepted by the annotations #PathVariable and #RequestParam.
To check and confirm the behavior I have created a spring boot application that contains only 1 controller.
#RestController
public class Controller
{
#GetMapping("/pvar/{pdata}")
public #ResponseBody String testPathVariable(#PathVariable(name="pdata") String pathdata)
{
return pathdata;
}
#GetMapping("/rpvar")
public #ResponseBody String testRequestParam(#RequestParam("param") String paramdata)
{
return paramdata;
}
}
Hitting following Requests I got the same response:
localhost:7000/pvar/!##$%^&*()_+-=[]{}|;':",./<>?
localhost:7000/rpvar?param=!##$%^&*()_+-=[]{}|;':",./<>?
!# was received as response in both the requests
#RequestParam:We can say it is query param like a key value pair
#PathVariable:-It is came from URI
I am a newbie on Spring framework and maybe this is an easy question.
I have a link as follows and attempt Spring controller handles the value"201610061023" of this link.However,my code did not work.
I know this value can be attached as a parameter or pathvariable in path but I just curious can I pass this value implicitly?
Thank you very much.
201610061023
#RequestMapping(value = "/Order")
public String requestHandlingMethod(#ModelAttribute("test") String name, HttpServletRequest request) {
return "nextpage";
}
Spring will not handle the title of the link simply because the title of the link will not be sent by the browser. To send it you can either:
add the value as parameter: 201610061023
add the value as path variable: 201610061023
add a JavaScript that will copy the title onClick into the href or send the generated URL with document.location. This can be automated, but it's pretty uncommon.
Your a-tag is wrong, you need to submit the id, there is no implicit way to submit the link-text (except a lot of java script code)!
201610061023
#RequestMapping(value = "/Order/{orderId}")
public String requestHandlingMethod(#PathVariable("orderId") long orderId, #ModelAttribute("test") String name, HttpServletRequest request) {
return "nextpage";
}
or
201610061023
#RequestMapping(value = "/Order")
public String requestHandlingMethod(#RequestParam("orderId") long orderId, #ModelAttribute("test") String name, HttpServletRequest request) {
return "nextpage";
}
See #RequestParam vs #PathVariable for the difference between this two approaches
I would like to know how to read a flash attributes after redirection in Spring MVC 3.1.
I have the following code:
#Controller
#RequestMapping("/foo")
public class FooController {
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(...) {
// I want to see my flash attributes here!
}
#RequestMapping(value = "/bar", method = RequestMethod.POST)
public ModelAndView handlePost(RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttributes("some", "thing");
return new ModelAndView().setViewName("redirect:/foo/bar");
}
}
What I am missing?
Use Model, it should have flash attributes prepopulated:
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(Model model) {
String some = (String) model.asMap().get("some");
// do the job
}
or, alternatively, you can use RequestContextUtils#getInputFlashMap:
#RequestMapping(value = "/bar", method = RequestMethod.GET)
public ModelAndView handleGet(HttpServletRequest request) {
Map<String, ?> inputFlashMap = RequestContextUtils.getInputFlashMap(request);
if (inputFlashMap != null) {
String some = (String) inputFlashMap.get("some");
// do the job
}
}
P.S. You can do return return new ModelAndView("redirect:/foo/bar"); in handlePost.
EDIT:
JavaDoc says:
A RedirectAttributes model is empty when the method is called and is
never used unless the method returns a redirect view name or a
RedirectView.
It doesn't mention ModelAndView, so maybe change handlePost to return "redirect:/foo/bar" string or RedirectView:
#RequestMapping(value = "/bar", method = RequestMethod.POST)
public RedirectView handlePost(RedirectAttributes redirectAttrs) {
redirectAttrs.addFlashAttributes("some", "thing");
return new RedirectView("/foo/bar", true);
}
I use RedirectAttributes in my code with RedirectView and model.asMap() method and it works OK.
Try this:
#Controller
public class FooController
{
#RequestMapping(value = "/foo")
public String handleFoo(RedirectAttributes redirectAttrs)
{
redirectAttrs.addFlashAttribute("some", "thing");
return "redirect:/bar";
}
#RequestMapping(value = "/bar")
public void handleBar(#ModelAttribute("some") String some)
{
System.out.println("some=" + some);
}
}
works in Spring MVC 3.2.2
For all those like me who were having problems with seeing the POST url in the browser when a validation would fail.
The POST url is a private url that should not be exposed to users but it was automatically rendered when a validation failed. i.e. if a field was below a minimum length. I was using #Valid. I wanted the original GET url of the form to show at all times even when validation bounced back to the form, so I did the following:
if (validation.hasErrors()) {
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.story", validation);
redirectAttributes.addFlashAttribute("story", story);
return new ModelAndView("redirect:/january/2015");
where story is the form object representation, redirectAttributes are RedirectAttributes you put in the method signature and validation is the BindingResult. /january/2015 is the mapping to the GET controller where the form lives.
After this implementation, in the mapping for /january/2015, story comes in intact as follows:
Story story= (Story) model.asMap().get("story");
//story from the POST method
I had to augment my GET method and check if this was not null. If not null, then send this to the form else I would send a newly initialized Story type to the form as default behaviour before.
In this manner, I am able to return to the form with the bindingresults intact (errors show on form) but have my GET url in place of the post url.
#RequestMapping(value = {"/userDetails", "/userDetails/edit/{id}"}, method = RequestMethod.GET)
public String userDetails(Map Model,****) {
//what goes here?
}
What will be my arguments to the userDetails method? And how do I differentiate /userDetails and /userDetails/edit/9 within the method?
Ideally we can get pathvariable by using annotation #PathVariable in method argument but here you have used array of url {"/userDetails", "/userDetails/edit/{id}"} so this will give error while supply request like localhost:8080/domain_name/userDetails , in this case no id will be supplied to #PathVariable.
So you can get the difference (which request is comming through) by using argument HttpServletRequest request in method and use this request object as below -
String uri = request.getRequestURI();
Code is like this -
#RequestMapping(value = {"/userDetails", "/userDetails/edit/{id}"}, method=RequestMethod.GET)
public String userDetails(Map Model,HttpServletRequest request) {
String uri = request.getRequestURI();
//put the condition based on uri
}