SpringMVC之Controller和参数绑定
在上一篇Spring+SpringMVC+Mybatis整合中说到了SSM的整合,并且在其中添加了一个简单的查询功能,目的只是将整个整合的流程进行一个梳理,下面在上一篇中工程的基础上再说一些关于SpringMVC的Controller的一些细节。
首先附上整个项目结构图,附上整个代码工程的下载地址,下面所讲到的测试用例都是在下面这个测试项目的基础上进行的。
一、关于Controller的注解形式
1、使用@Controller注解可以实现Controller的注解开发,然后在springmvc.xml的配置文件中配置注解扫描器,就可以使用注解形式进行Controller的开发,下面我们简单使用一个helloworld的例子进行说明
①在springmvc.xml中配置注解扫描器
其中也当然包含springmvc所需要的处理器映射器、处理器适配器、视图解析器(这几个组件个概念可以查看SpringMvc入门,其中开篇说到了SpringMVC的处理流程和各个组件以及之间的关系),我们这里直接使用下面的配置方式进行配置
②写一个简单的helloworld,在浏览器中请求对应的Controller,然后输出在页面上
package cn.test.ssm.controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; @Controller
public class HelloWorldController { @RequestMapping("/helloWorld.do")
public ModelAndView helloWorld() throws Exception{
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("test","HelloSSM");
modelAndView.setViewName("/WEB-INF/items/hello.jsp");
return modelAndView;
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
测试Controller
${test}
</body>
</html>
hello.jsp
③然后在地址栏中请求http://localhost:8080/TestSSM2/helloWorld.do,输出
二、关于RequestMapping
1、使用不同的处理器映射规则
a、我们通过RequestMapping 可以使用不同的处理器映射规则,RequestMapping注解能够控制http请求的路径和方式(get、post......),在同一个Controller中可以写不同的映射方法,映射浏览器不同的请求业务。
具体的使用方式就是:@RequestMapping(value="/test.do")或@RequestMapping("/test),其中value的值是数组,可以将多个url映射到同一个方法
b、下面我们就在上一篇中查询列表的基础上增加查询详细信息的一个功能,通过RequestMapping注解来实现
①首先在mapper中将ProductDemo.xml中添加查询详细信息的Sql配置
<select id="queryProductInfo" parameterType="java.lang.Integer" resultType="cn.test.ssm.po.ProductExtend">
SELECT pname,shop_price FROM product WHERE pid = #{id}
</select>
②在mapper接口中添加上面的方法
③在service接口中添加相应的方法和方法实现
service接口
接口实现类
④在controller层中加上queryInfo方法,其中使用RequestMapping映射了两个不同请求对应的方法实现
package cn.test.ssm.controller; import cn.test.ssm.po.ProductExtend;
import cn.test.ssm.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import java.util.List; @Controller
public class ProductController { @Autowired
private ProductService productService; @RequestMapping("/queryList.do")
public ModelAndView queryList() throws Exception{
//从service层调用方法
List<ProductExtend> productExtendList = productService.findProductListByName(null);
//返回ModelandView
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject(productExtendList);
modelAndView.setViewName("/WEB-INF/items/itemsList.jsp");
return modelAndView;
} @RequestMapping("/queryInfo.do")
public ModelAndView queryInfo() throws Exception { ProductExtend productExtend = productService.queryProductInfo(1);
productExtend.setDesc("这是相机");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject(productExtend);
modelAndView.setViewName("/WEB-INF/items/editItem.jsp");
return modelAndView;
}
}
⑤最后在查询列表中点击查询即可查看详细信息
2、窄化请求映射
a)为了实现不同模块之间的开发,我们可以进行这样的使用:在class上添加@RequestMapping(url)指定通用请求前缀, 限制此类下的所有方法请求url必须以请求前缀开头,通过此方法对url进行分类管理。
b)如下:@RequestMapping放在类名上边,设置请求前缀
@Controller
@RequestMapping("/test")
然后在方法名上边设置请求映射url:
@RequestMapping("/queryItem ")
访问地址为:http://localhost:8080/TestSSM2/test/queryList.do
3、关于http请求方式限定
a)限定POST方法:@RequestMapping(method = RequestMethod.POST)
如果通过Get访问则报错:HTTP Status 405 - Request method 'GET' not supported,例如
然后访问http://localhost:8080/TestSSM2/test/queryList.do,就会是下面的错误
b)限定GET方法:@RequestMapping(method = RequestMethod.GET)
如果通过Post访问则报错:HTTP Status 405 - Request method 'POST' not supported
c)GET和POST都可以:@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
三、关于Controller的返回值问题
1、返回ModelAndView
a)我们上面编写Controller都是以这种方式进行的,大概就是定义一个ModelAndView对象,然后填充模型(从数据库中得到的数据)和逻辑视图(指定的jsp等路径),并返回即可
b)例如
2、使用void类型
a)在controller方法形参上可以定义request和response,使用request或response指定响应结果:
①使用request转向页面:request.getRequestDispatcher("页面路径").forward(request, response);
例如:
@RequestMapping("/test_void.do")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception{
request.setAttribute("test","返回值为void类型的测试");
request.getRequestDispatcher("/WEB-INF/items/hello.jsp").forward(request,response);
}
然后输出结果
②通过response页面重定向:response.sendRedirect("url"),实现方式同上
3、使用String作为返回值
a)Controller中的方法形参为model,然后通过形参将数据返回到请求页面上,最后返回字符串可以指定逻辑视图名(路径信息),通过视图解析器解析为物理视图地址;
@RequestMapping("/testString.do")
public String testString(Model model) throws Exception {
//其他进行的操作
//通过形参model将数据返回到请求页面上 类似于返回ModelAndView中的addObject方法
model.addAttribute("testString","testString");
//然后返回逻辑视图名,经过视图解析器解析为相应的jsp等路径
return "test/helloWorld";
}
b)重定向:Contrller方法返回结果重定向到一个url地址,但是由于重定向之后原来的request中的数据不在,所以如果要传参数可以/item/queryItem.action后边加参数:/test/queryTest?test1Key=test1Value&test2Key=test2Value
c)转发:Controller中的方法执行后继续执行另一个controller方法,如下信息modify提交后转向到信息显示页面,修改信息的id参数可以带到修改方法中。//结果转发到update.action,request可以带过去:return "forward:update.action";forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。转发并没有执行新的request和response,而是和转发前的请求共用一个request和response。所以转发前请求的参数在转发后仍然可以读取到。
四、关于SpringMVC的参数绑定问题
1、参数绑定过程
a)参数绑定:注解适配器对RequestMapping标记的方法进行适配,将从浏览器中请求的数据(key/value或者表单信息)在方法中的形参会进行参数绑定,所以在springmvc中的参数绑定是通过Controller的方法形参进行绑定的。
b)参数绑定所支持的默认参数类型,可以直接在Controller方法上面定义下面类型的形参,然后在方法体内直接使用
①HttpServletRequest(通过request对象获取请求信息)
②HttpServletResponse(通过response处理响应信息)
③HTTPSession(通过session对象得到session中存放的对象)
④Model(通过model向页面传递数据,然后页面通过${test.XXXX}获取item对象的属性值。如同上面Controller中方法返回值为String的情况)
2、RequestParam注解使用
a)在没有使用注解的时候,我们在前端提交参数的key名字应该Controller中方法的形参相同,否则在request域中无法进行匹配。当我们需要将Controller方法中的形参设置为不一样的参数名时候,就需要使用这个注解
b)注解简介:@RequestParam用于绑定单个请求参数。
①value:参数名字,即入参的请求参数名字,如value=“test_id”表示请求的参数区中的名字为test_id的参数的值将传入;
②required:是否必须传入参数,默认是true,表示请求中一定要有相应的参数,否则将报HTTP Status 400 - Required Integer parameter 'XXXX' is not present
③defaultValue:默认值,表示如果请求中没有同名参数时的默认值
比如:形参名称为id,但是这里使用value=" test_id"限定请求的参数名为test_id,所以页面传递参数的名必须为test_id。
注意:如果请求参数中没有test_id将抛出异常:HTTP Status 500 - Required Integer parameter 'test_id' is not present
这里通过required=true限定itest_id参数为必需传递,如果不传递则报400错误,可以使用defaultvalue设置默认值,即使required=true也可以不传item_id参数值
c)下面使用例子来进行说明上面的几点内容
①测试注解
测试工程如同上一篇SSM整合中搭建的工程,其中只有一个功能就是查询列表。然后我们在本篇最开始的时候介绍RequestMapping时候添加了查询详细信息的功能,但是其中我们没有接收前端传入的数据,全部都是用的默认值1,下面来将这个方法使用RequestParam进行改写,接收前端传入的参数进行查询。
@RequestMapping("/queryInfo.do")
public ModelAndView queryInfo(@RequestParam(value = "id") Integer testId) throws Exception {
//在没有使用注解的时候,方法形参中的参数名需要和前端请求的key名称一样,使用之后就可以自定义
ProductExtend productExtend = productService.queryProductInfo(testId); productExtend.setDesc("这是相机");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject(productExtend);
modelAndView.setViewName("/WEB-INF/items/editItem.jsp");
return modelAndView;
}
然后我们再次进行测试,首先访问http://localhost:8080/TestSSM2/test/queryList.do,然后查看id=2的信息
得到下面的结果
在对比id=1的时候
②测试required
在上面的方法中加上
然后进行测试,输入http://localhost:8080/TestSSM2/test/queryInfo.do,不加参数,则报出下面的错误
③测试defaultValue
当required设置为true的时候,如果没有传入key/value,当在Controller中设置defaultValue的时候也不会报出上面的异常,在Controller方法参数中改成下面这样
然后直接输入http://localhost:8080/TestSSM2/test/queryInfo.do不加id参数,还是能够查询到默认的id=1的数据
3、普通POJO类型绑定
a)将pojo对象中的属性名和传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中 ,然后在Contrller方法定义: 请求的参数名称和pojo的属性名称一致,会自动将请求参数赋值给pojo的属性。
b)我们现在在Controller中新添加一个下面的方法,输出从页面上面提交的数据
c)在页面表单中点击提交数据
然后后台中输出
4、自定义参数绑定
a)定义一个Date类型的参数绑定,首先建议里个转换器的java工具类,用来将String转换为java.util.Date类型
package cn.test.ssm.controller.converter; import org.springframework.core.convert.converter.Converter; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; public class StringToDateConverter implements Converter<String, Date> {
@Override
public Date convert(String s) { try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
然后在springmvc.xml中配置上上面的转换器
<!--配置mvc:annotation代替基于注解方式的处理器映射器和适配器的配置-->
<mvc:annotation-driven conversion-service="converterService"></mvc:annotation-driven> <bean id="converterService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!--配置转换器-->
<property name="converters">
<list>
<bean class="cn.test.ssm.controller.converter.StringToDateConverter"></bean>
</list>
</property>
</bean>
最后可以修改一下上面的查看信息方法,在后台中打印出所有提交的数据,注意下面的方法中形参createtime的类型已经设置为Date类型,在前端页面中也添加上了createtime的输入
@RequestMapping("/printInfo.action")
public String printInfo(Product product, Date createtime) throws Exception {
System.out.println("输出信息"+product);
System.out.println(createtime);
return "forward:queryList.do";
}
最后在浏览器中进行如下输入测试,输入一个日期类型
最后在后台查看打印的信息
5、自定义包装类型
a)当前天传入的参数比较复杂的时候(比如说涵盖不同数据实体类之间关联的查询或者某个实体类的扩展属性信息),这个时候我们可以在扩展类中加上额外的属性然后将其作为我们自定义的包装类的属性,然后将前台页面传入参数的name设置为包装类的属性名.实体类属性(testExtend.name)
b)看下面的例子,这是一个模糊查询的简单功能实现
①我们首先在实体类Product的扩展类ProductExtend中添加接受模糊查询参数的一个属性
②然后定义一个包装类型,其中将上面的扩展类型设置为一个属性
③然后就在Controller方法中将自定义的包装类型设置为方法形参,用以进行参数绑定,并且调用service的方法进行查询
④在前台中查看查询
⑤在debug模式中查看是否接收到前端传入的参数,发现可以接收到页面传入的参数
并且在调用service方法之后的查询结果也为
最终页面显示结果
SpringMVC之Controller和参数绑定的更多相关文章
- SSM框架之SpringMVC(2)参数绑定及自定义类型转换
SpringMVC(2)参数绑定及自定义类型转换 1.请求参数的绑定 1.1. 请求参数的绑定说明 1.1.1.绑定机制 表单提交的数据都是k=v格式的 username=haha&passw ...
- JAVAEE——SpringMVC第一天:介绍、入门程序、架构讲解、SpringMVC整合MyBatis、参数绑定、SpringMVC和Struts2的区别
1. 学习计划 第一天 1.SpringMVC介绍 2.入门程序 3.SpringMVC架构讲解 a) 框架结构 b) 组件说明 4.SpringMVC整合MyBatis 5.参数绑定 a) Sp ...
- springMVC第二天——高级参数绑定与其它特性
大纲摘要: 1.高级参数绑定 a) 数组类型的参数绑定 b) List类型的绑定 2.@RequestMapping注解的使用 3.Controller方法返回值 4.Springmvc中异常处理 5 ...
- SpringMVC中的自定义参数绑定案例
由于日期数据有很多种格式,所以springmvc没办法把字符串转换成日期类型.所以需要自定义参数绑定.前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适 ...
- SpringMVC框架笔记02_参数绑定返回值文件上传异常处理器JSON数据交互_拦截器
目录 第1章 高级参数的绑定 1.1 参数的分类 1.2 数组类型的参数的绑定 1.3 集合类型的参数的绑定 第2章 @RequestMapping的用法 2.1 URL路径映射 2.2 请求方法限定 ...
- Springmvc入门基础(四) ---参数绑定
1.默认支持的参数类型 处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值. 除了ModelAndView以外,还可以使用Model来向页面传递数据, Model是一个接口,在参数里直接声明 ...
- SpringMVC基础学习(三)—参数绑定
一.基本数据类型的绑定 页面 <form action="${pageContext.request.contextPath}/test.do" method="p ...
- SpringMVC框架三:参数绑定
这篇文章整合了SpringMVC和MyBatis: https://www.cnblogs.com/xuyiqing/p/9419144.html 接下来看看参数绑定: 默认Conrtroller可以 ...
- Springmvc的handler method参数绑定常用的注解
转自:http://blog.longjiazuo.com/archives/1149 1. 简介: handler method参数绑定常用的注解,我们根据他们处理的Request的不同内容部分 ...
随机推荐
- BZOJ_2343_[Usaco2011 Open]修剪草坪 _单调队列_DP
BZOJ_2343_[Usaco2011 Open]修剪草坪 _单调队列_DP 题意: N头牛,每头牛有一个权值,选择一些牛,要求连续的不能超过k个,求选择牛的权值和最大值 分析: 先考虑暴力DP,f ...
- 【毕业原版】-《伦敦艺术大学毕业证书》UAL一模一样原件
☞伦敦艺术大学毕业证书[微/Q:865121257◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...
- React Native开发 - 搭建React Native开发环境
移动开发以前一般都是原生的语言来开发,Android开发是用Java语言,IOS的开发是Object-C或者Swift.那么对于开发一个App,至少需要两套代码.两个团队.对于公司来说,成本还是有的. ...
- 小程序 textarea、input 层级过高,导致填写内容穿透,z-index无效问题解决方案。
小程序的textare.input输入框层级是最高的 那么我们在textare.input输入的内容就会总是显示在最上一层. 这是时为什么呢?官方文档有说明,因为textare.input这些是原生组 ...
- MIUI目前为止最简单安装谷歌服务框架教程
安装谷歌服务框架方法有很多,比如用第三方 rec卡刷gapps包.用第三方工具安装......然而这些对于新手来说还是比较难的! 我今天说的方法可以说是最简单的:1.不需要修改文件:2.不需要借助第三 ...
- C#相等性 - “==”
今天写一下C#里的“==”这个操作符. 原始类型 假象 在刚学C#的时候,我以为C#里的==和.NET里的object.Equals()方法是一样的,就是一个语法糖而已.其实它们的底层机制是不一样的, ...
- Unity 用ml-agents机器学习造个游戏AI吧(1)(Windows环境配置)
前言:以前觉得机器学习要应用于游戏AI,还远得很. 最近看到一些资料后,突发兴致试着玩了玩Unity机器学习,才发觉机器学习占领游戏AI的可能性和趋势. Unity训练可爱柯基犬Puppo 机器学习训 ...
- JS异步操作新体验之 async函数
1.初识 async 函数 ES6中提供了两个很好的解决异步操作的方案 Promise 和 Generator,ES2017标准中引入的 async 函数就是建立在 Promise 和 Gener ...
- Nginx技术进阶详讲
Nginx技术进阶详讲 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 并发数问题 讲到并发数这个概念,想必各位应该都知道是什么意思,就是同时访问一个项目,就比我们现在做的一些项目完 ...
- C# 操作Word页眉页脚——奇偶页/首页不同、不连续设置页码、复制页眉页脚、锁定页眉页脚、删除页眉页脚
前言 本文是对Word页眉页脚的操作方法的进一步的阐述.在“C# 添加Word页眉页脚.页码”一文中,介绍了添加简单页眉页脚的方法,该文中的方法可满足于大多数的页眉页脚添加要求,但是对于比较复杂一点的 ...