1 Controller到View的参数传递
在Spring MVC中,把值从Controller传递到View共有5中操作方法,分别是。
- 使用HttpServletRequest或HttpSession。
- 使用ModelAndView。
- 使用Map集合
- 使用Model
- 使用ModelMap
使用HttpServletRequest或HttpSession传值
使用HttpServletRequest或HttpSession传值,和Servlet传值方式是一致的,因此应用的不是太多。在学习Servlet的时候,用户登录等情况下,是要把当前登录的用户对象保存在HttpSession中的,这是为数不多的几个应用之一。具体使用HttpServletRequest或者HttpSession的操作代码如下。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;/*** 用户模块控制器*/
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(value="/list", method=RequestMethod.GET)public String list(HttpServletRequest req, HttpSession session) {req.setAttribute("test1", "测试数据1");session.setAttribute("test2", "测试数据2");return "user/list";}
}
使用HttpServletRequest或者HttpSession传值,只需要把HttpServletRequest对象和HttpSession对象当做参数传到方法中就可以直接使用了。
在页面中取值的时候就可以使用EL表达式,通过${test1 }和${test2 },获取到相应的数据。
使用ModelAndView传值
在本章一开始简单使用了一次,不过没有传值,使用ModelAndView传值具体的操作为。
@RequestMapping(value="/modelAndView", method=RequestMethod.GET)
public ModelAndView testModelAndView() {Map<String, String> data = new HashMap<String, String>();data.put("test", "测试数据");return new ModelAndView("user/modelAndView", data);
}
在页面modelAndView.jsp中取值,同样可以采用EL表达式取值。使用ModelAndView传值需要借助于集合,因此在具体的开发中基本不会用到,在此只做简单的了解。
使用Map集合传值
在使用Map集合传值的时候,只需要把一个Map对象当做方法的参数就可以使用了,具体的操作为。
@RequestMapping(value="/map", method=RequestMethod.GET)
public String testMap(Map<String, Object> data) {data.put("test", "测试数据");return "user/map";
}
在页面中map.jsp中取值,同样采用EL表达式${test }取值。
使用Model传值
Model是一个接口,在具体的操作中,也是把Model对象当做方法的参数,具体的操作为。
@RequestMapping(value="/model", method=RequestMethod.GET)
public String testModel(Model model) {model.addAttribute("test", "测试数据");return "user/model";
}
在页面中map.jsp中取值,同样采用EL表达式${test }取值。Model的addAttribute方法还有另外的一个重载,如下所示。
@RequestMapping(value="/model", method=RequestMethod.GET)
public String testModel(Model model) {model.addAttribute("测试数据");return "user/model";
}
在页面map.jsp中取值,是采用EL表达式${string }来取值,因为,使用model.addAtttribute(data)直接传值,没有指定其key值,默认的key值是数据的类型(首字母变成小写)。这种方法主要是应用在添加一个对象,只需要把一个对象传入到方法中,默认的key值就是该对象的类型。
使用ModelMap传值
提起ModelMap,我们就可以大致觉得这是Model和Map的组合,其实也基本差不多。不过ModelMap并没有实现Model接口,只是继承了LinkedHashMap,而LinkedHashMap继承自HashMap。ModelMap具有Model和Map相同的操作,不过在具体的开发中使用的也不是太多。
总结
虽然参数从Controller传递到View有5中不同的操作方法,但是在具体的使用上一般只会采用其中的Model和Map进行传值,大家具体使用哪一种方法,要看具体的操作,本书在接下来的章节中全部采用Model进行传值。
2 View到Controller的参数传递
在Spring MVC中View到Controller的传值,可以通过在URL之后通过问号传值,也可以通过表单提交传值。不过在Controller中接收数据的时候,不需要再使用HttpServletRequest对象的getParameter方法了。具体操作的时候,只需要在方法中,把要传递数据的参数名当做方法的一个参数就可以了。比如现在有一个链接地址为:http://localhost:8080/springmvc/user/show?username=test,在具体的方法中操作为。
@RequestMapping(value="/show", method=RequestMethod.GET)
public String show(String username) {System.out.println(username);return "user/show";
}
这种方式,如果在访问的时候没有传值,也能正常访问,不会有什么问题。但是如果要求一个参数必须传递,可以在具体的参数之前加入注解@RequestParam,意为请求中必须包含该参数,具体的代码为。
@RequestMapping(value="/show", method=RequestMethod.GET)
public String show(@RequestParam("username") String username) {System.out.println(username);return "user/show";
}
此时,会把该参数当做请求的一部分,如果没有传值,会出现400错误(请求格式错误),如图所示。
通过表单提交也同样能够完成传值,首先定义一个方法,用以跳转到添加页面,具体的操作为。
/*** 跳转到add.jsp页面*/
@RequestMapping(value="/add", method=RequestMethod.GET)
public String add() {return "user/add";
}
在页面add.jsp中添加以下表单代码。
<form action="user/add" method="post">username:<input type="text" name="username"><br>password:<input type="password" name="password"><br>nickname:<input type="text" name="nickname"><br><input type="submit" value="提交">
</form>
接下来定义接收数据的方法,由于表单提交方式是POST,方法处理提交的方式也就为POST,具体的代码如下。
/*** 执行具体的数据添加*/
@RequestMapping(value="/add", method=RequestMethod.POST)
public String add(String username, String password, String nickname) {System.out.println(username + "," + password + "," + nickname);return "redirect:/user/list";
}
注意:和上一个方法的方法名一样,请求地址也一样,访问不同的方法就是要靠请求类型来区别。
通过测试结果发现,数据能够正常的传递过来。不过有可能会出现中文乱码,这是因为,Spring MVC并没有做字符编码处理,我们只需要按照过滤器的操作来处理就可以了,具体的操作方法再此就不再讲述。
通过这种操作,我们发现这种操作效率没有比Servlet高出多少,传递的参数多了,相对应的方法中的参数也就必须增多,同样也是不太方便。因此我们设想,能不能在页面中用一个对象来封装所有的数据呢,这样提交的数据就包含在了这个对象中,这样在处理方法中只需要接收这个对象,不就解决了传参过多的问题了吗?
Spring MVC就提供了上述这种操作方法,可以大大简化操作。解决方法是,首先在跳转到添加页面之前,把一个对象添加到Model中,然后在页面中的表单里指定要封装的对象,然后提交表单,在处理方法中处理这个对象即可。Spring MVC解决方法是,首先在跳转到页面中的方法里,往Model对象中添加一个对象,具体的代码为。
/*** 跳转到add.jsp页面*/
@RequestMapping(value="/add", method=RequestMethod.GET)
public String add(Model model) {//往Model对象里添加一个对象model.addAttribute(new User());return "user/add";
}
注意:此时使用addAttribute方法里只有一个参数,key值就为对象的类型,也就是“user”。
在页面代码中处理的时候,需要使用到Spring MVC的表单标签,在使用的时候需要先导入Spring MVC的表单标签库,具体代码为。
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
导入的方式和之前导入JSTL的方式类似,在使用的时候就可以通过“<sf:> ”来引入表单标签,接下来修改页面的表单标签,具体代码为。
<sf:form method="post" modelAttribute="user">username:<sf:input path="username"/><br>password:<sf:password path="password"/><br>nickname:<sf:input path="nickname"/><br><input type="submit" value="提交"/>
</sf:form>
注意:此时的表单中没有指定action,其实在Spring MVC的表单标签中,action可以指定,也可以不指定,如果不指定提交的地址就为到达该页面的地址,简单的说就从哪来回哪去。
此时是表单提交,因此提交方式应该是POST提交。form表单中的modelAttribute属性就是指定要往哪一个对象中封装数据,也就是为该表单绑定一个模型对象,如果没有绑定对象,系统会到request对象中寻找command的表单bean,如果还没有找到页面就会报错。“<sf:input path=”username”/>”对应JSTL中的“<input type=”text”name=”username”/>”,其中的username一定要为user对象中的属性,并且要有相应的getter和setter方法,此时,在表单提交的同时,会把该属性值封装到对象user中,其他的标签以此类推。
在具体的添加操作方法中,就可以直接接收一个user对象了,代码如下。
/*** 执行具体的数据添加*/
@RequestMapping(value="/add", method=RequestMethod.POST)
public String add(User user) {System.out.println(user);return "redirect:/user/list";
}
有了这种操作方式,不管提交的数据有多少,在具体的处理中都是同样的简单。