SpringMVC主要做的就两方面的操作。
- 在Controller接收从jsp传递过来的数据
- 把Controller的数据传递到jsp页面
将Controller里边的数据传到jsp
其返回值有三种类型
* ModelAndView
* void
* String
@Controller
public class Test {
@RequestMapping(value="/test2")
public ModelAndView test2() throws Exception{
String num="2";
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("item",num);
modelAndView.setViewName("/WEB-INF/jsp/test.jsp");//重定向为"redirect:url路径"
return modelAndView;
}
@RequestMapping(value="/test3")
public String test3(Model model) throws Exception{
String num="2";
model.addAttribute("item", num);
return "/WEB-INF/jsp/test.jsp";//默认是forward
//return "redirect:url路径";
//return "forward:url路径";
}
@RequestMapping(value="/test4")
public void test4(HttpServletRequest request,HttpServletResponse response) throws Exception{
String num="2";
request.setAttribute("item", num);
request.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(request, response);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 返回ModelAndview:Controller方法中定义ModelAndView对象并返回,对象中可以添加model数据,指定view。
- 返回void:在Controller方法形参上可以定义request和response,使用request或response指定响应结果。
//转发
request.getRequestDispatcher("页面路径").forward(request, response);
//重定向
response.sendRedirect("url")
//通过response指定响应结果,例如响应json数据:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 返回字符串
Controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
//重定向,到jsp页面或action
return "redirect:queryItem.action";
//如果要传参数可以在后边加参数
/item/queryItem?name=q&age=22
//转发,默认为转发
return "forward:queryItem.action";
- 1
- 2
- 3
- 4
- 5
- 6
- 7
从jsp传递数据到Controller
处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值
- HttpServletRequest
- HttpServletResponse
- HttpSession
- Model
绑定简单类型
当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。
@RequestMapping(value="/test6")
public void test6(Integer num) throws Exception{
System.out.println(num);
}
- 1
- 2
- 3
- 4
- 5
- 6
在浏览器中访问http://localhost:8080/springmvctest/test6.action?num=9
会在控制台打印出9
对日期类型的绑定
springmvc没有提供默认的对日期类型的绑定,需要自定义日期类型的绑定。
建立一个CustomDateConverter.java
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.core.convert.converter.Converter;
public class CustomDateConverter implements Converter<String,Date>{
@Override
public Date convert(String source) {
try {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(source);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
在springmvc.xml中配置
<!-- 配置注解驱动 -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 转换器 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="cn.itcast.springmvc.first.converter.CustomDateConverter"/>
</list>
</property>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
@RequestMapping(value="/test9")
public void test9(Date date) throws Exception{
System.out.println(date);
}
- 1
- 2
- 3
- 4
- 5
- 6
配置转换类去除空格
还可以配置一个转换类,把通过http请求传过来的字符串的两边去除空格。
import org.springframework.core.convert.converter.Converter;
public class StringTrimConverter implements Converter<String,String>{
@Override
public String convert(String source) {
try {
//去掉字符串两边的空格,如果去除后为空设置为null
if (source!=null) {
source=source.trim();
if (source.equals("")) {
return null;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return source;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
<!-- 转换器 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="cn.itcast.springmvc.first.converter.CustomDateConverter"/>
<bean class="cn.itcast.springmvc.first.converter.StringTrimConverter"/>
</list>
</property>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
注解@RequestParam
@RequestMapping(value="/test7")
public void test7(@RequestParam(value = "item_num", required = false, defaultValue = "1")Integer num) throws Exception{
System.out.println(num);
}
- 1
- 2
- 3
- 4
- 5
- 6
value:定义请求参数的名字。
在浏览器中访问http://localhost:8080/springmvctest/test7.action?item_num=101
此时请求参数为item_num,形参为num,也可以完成绑定。
required:是否必须传入,默认是true,表示请求中一定要有相应的参数,否则会报错
HTTP Status 400 - Required Integer parameter ‘item_num’ is not present
defaultValue:默认值,表示如果请求中没有此参数时的默认值。
这个注解不太常用,一般都把请求参数和形参定义成一样的。
绑定简单pojo
如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中。
建立一个Person类
public class Person {
private String name;
private Integer age;
//此处省略get和set方法
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", toString()=" + super.toString() + "]";
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
@RequestMapping(value="/test7")
public void test7(Person person) throws Exception{
System.out.println(person);
}
- 1
- 2
- 3
- 4
- 5
- 6
在浏览器中访问http://localhost:8080/springmvctest/test7.action?name=LiMing&age=12
会在控制台打印出
Person [name=LiMing, age=12, toString()=cn.itcast.springmvc.po.Person@3be8a]
- 1
绑定包装pojo
如果controller方法形参中有多个pojo且pojo中有从重复的属性,使用简单pojo绑定无法有针对性的绑定。比如:方法形参有items和user,pojo中同时存在name属性,从http请求过程的name无法有针对性的绑定到items或user。
这样的话可以定义一个包装类型,一个pojo里边包含一个pojo。
建立一个PersonVo
public class PersonVo {
private Person person;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
@RequestMapping(value="/test8")
public void test8(PersonVo personVo) throws Exception{
System.out.println(personVo.getPerson().getName());
}
- 1
- 2
- 3
- 4
- 5
- 6
在浏览器中访问http://localhost:8080/springmvctest/test8.action?person.name=LiMing&person.age=12
会在控制台打印出LiMing
处理乱码
post乱码
在web.xml中加入过滤器
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
get乱码
有两种处理方法
第一种
修改tomcat配置文件添加编码与工程编码一致,要修改的配置文件在
D:\Java\apache-tomcat-7.0.52\conf\server.xml. 更改内容如下:
<Connector URIEncoding="utf-8"connectionTimeout="20000" port="8080" protocol="HTTP/1.1"redirectPort="8443"/>
- 1
第二种
对参数进行重新编码
String userName=new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8");
- 1
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
此时获取的userName是经过ISO8859-1编码过的。现在需要做的是按照ISO8859-1的编码方式把username再变成最原始的字节码(即刚从浏览器端传过来的东西,没有经过编码过的),然后再把这个字节码通过utf-8的方式进行编码。
数据回显
简单类型回显
需求:表单出现错误,重新回到表单,用户重新填写数据,刚才提交的参数在页面上回显。
<form action="${pageContext.request.contextPath }/test11.action" method="post">
<input type="text" name="q" value="${item}">
<input type="submit"/>
</form>
- 1
- 2
- 3
- 4
- 5
- 6
//这个方法就相当于跳转到编辑页面之前的查询操作,把数据都查出来,然后传到编辑页面
@RequestMapping(value="/test10")
public String test10(Model model) throws Exception{
String a="qqq";
model.addAttribute("item", a);
return "a.jsp";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
//这个是在编辑页面点击提交按钮之后所作的操作,
@RequestMapping(value="/test11")
public String test11(Model model,String q) throws Exception{
model.addAttribute("item", q);//将数据回显到页面
return "a.jsp";//模拟报错时候跳回到原来的页面
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
测试的时候先在浏览器访问http://localhost:8080/springmvctest/test10.action
这时候会跳转到编辑页面,文本框显示内容qqq,然后点击提交按钮,会访问test11,这个方法模拟在提交过程中出了一些错误,要跳转会编辑页面(要保证编辑页面的内容即qqq还在),这就需要加一句话model.addAttribute(“item”, q);
要保证数据回显需要保证都为item,即保持一致
<input type="text" name="q" value="${item}">
model.addAttribute("item", a);
model.addAttribute("item", q);
- 1
- 2
- 3
pojo类型回显
第一种方法同上
第二种方法,用注解
<form action="${pageContext.request.contextPath }/test11.action" method="post">
<input type="text" name="name" value="${item.name}">
<input type="submit"/>
</form>
- 1
- 2
- 3
- 4
- 5
- 6
@RequestMapping(value="/test10")
public String test10(Model model) throws Exception{
Person p=new Person();
p.setName("李明");
model.addAttribute("item", p);
return "a.jsp";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
@RequestMapping(value="/test11")
public String test11(Model model,@ModelAttribute(value="item")Person per) throws Exception{
return "a.jsp";//模拟报错时候跳回到原来的页面
}
- 1
- 2
- 3
- 4
- 5
<input type="text" name="name" value="${item.name}">
model.addAttribute("item", p);
@ModelAttribute(value="item")Person per
- 1
- 2
- 3
都是item,要保持一致。
@ModelAttribute注解的其他用法
使用@ModelAttribute将公用的数据传到页面,这样就不用在每一个controller方法中通过Model将这些数据传到页面了。
@ModelAttribute("itemsType")
public Map<String,String> getItemsType()throws Exception{
HashMap<String,String> itemsType=new HashMap<String,String>();
itemsType.put("001", "数码");
itemsType.put("002", "服装");
return itemsType;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
<select>
<c:forEach items="${itemsType}" var="item">
<option value="${item.key }"</span>></span>${item.value}</option>
</c:forEach>
</select>
- 1
- 2
- 3
- 4
- 5
参数绑定集合类型
绑定数组
<form action="${pageContext.request.contextPath }/test12.action" method="post">
<input type="checkbox" name="delete_id" value="1" />
<input type="checkbox" name="delete_id" value="2" />
<input type="checkbox" name="delete_id" value="3" />
<input type="checkbox" name="delete_id" value="4" />
<input type="submit"/>
</form>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
@RequestMapping(value="/test12")
public void test12(Integer[] delete_id) throws Exception{
for (Integer i : delete_id) {
System.out.println(i);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
绑定List<Object>
在包装类PersonVo中建立一个personList字段
private List<Person> personList;
- 1
<body>
<form action="${pageContext.request.contextPath }/test14.action" method="post">
<table width="100%" border=1>
<c:forEach items="${personList }" var="p" varStatus="s">
<tr>
<td>
<input type="text" name="personList[${s.index }].name"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${p.name }"> </td>
<td>
<input type="text" name="personList[${s.index }].age"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${p.age }"> </td>
</tr>
</c:forEach>
</table>
<input type="submit"/>
</form>
</body>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
@RequestMapping(value="/test13")
public String test13(Model model) throws Exception{
List<Person> pList=new ArrayList<Person>();
Person p1=new Person();
Person p2=new Person();
p1.setName("LiMing");
p1.setAge(11);
p2.setName("Danny");
p2.setAge(22);
pList.add(p1);
pList.add(p2);
model.addAttribute("personList", pList);
return "a.jsp";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
@RequestMapping(value="/test14")
public void test14(PersonVo pVo) throws Exception{
List<Person> l=pVo.getPersonList();
for (Person i : l) {
System.out.println(i);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在浏览器中访问http://localhost:8080/springmvctest/test13.action
json数据的交互
json数据格式是比较简单容易理解,json数据格式常用于远程接口传输,http传输json数据,非常方便页面进行提交/请求结果解析,对json数据的解析。
导入jar包
- jackson-core-asl-1.9.11.jar
- jackson-mapper-asl-1.9.11.jar
如果用mvc:annotation-driven方式的话,就不用在springmvc.xml中配置json转换器了
<script type="text/javascript">
$(function(){
//请求json响应json
$("#requestJson").click(function(){
$.ajax({
url:"${pageContext.request.contextPath }/requestJson.action",
type:"post",
contentType:"application/json;charset=utf-8",
//请求json数据,使用json表示商品信息
data:'{"name":"李明","age":22}',
success:function(data){
alert(data.name);
}
});
});
//请求key/value响应json
$("#requestKeyValue").click(function(){
$.ajax({
url:"${pageContext.request.contextPath }/requestKeyValue.action",
type:"post",
data:"name=李明&age=22",
success:function(data){
alert(data.name);
}
});
});
});
</script>
</head>
<body>
<input type="button" value="请求json响应json" id="requestJson" />
<input type="button" value="请求key/value响应json" id="requestKeyValue" />
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
@RequestMapping("/requestJson")
public @ResponseBody Person requestJson(@RequestBody Person p)throws Exception{
return p;
}
@RequestMapping("/requestKeyValue")
public @ResponseBody Person requestKeyValue(Person p)throws Exception{
return p;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
@RequestBody:将请求的json数据转成java对象
@ResponseBody:将java对象转成json数据输出。
如果前端处理没有特殊要求建议使用第二种,请求key/value,响应json,方便客户端解析请求结果 。
SpringMVC主要做的就两方面的操作。