注解含义
@RequestMapping
当它既出现在类上也出现在方法上时,类上注解值为请求URL的一级目录,方法上注解值为请求URL的二级目录
value:别名
method:指定HTTP请求方法(可选RequestMethod.GET,RequestMethod.HEAD,RequestMethod.POST,RequestMethod.PUT等)
params:指定请求参数的限制
@RequestMapping(params={“param1”}),表示请求参数中param1必须出现
@RequestMapping(params={"!param1"}),表示请求参数中param1不能出现
headers:限定HTTP请求中必须包含的请求头,同样支持简单的表达式
@PathVariable:出现在RequestMapping的value中,设置占位符
// 控制器类
@Controller
public class HelloController {
@RequestMapping("/findAccount/{id}")
public void findAccount(@PathVariable(name = "id") Integer accountId) {
// accountId = 10
// 方法体...
}
}
访问URL:http://localhost:8080/findAccount/10会将10传给findAccount方法的accountId参数.
@RequestParam注解:
为处理器方法参数起别名
@RequestHeader
获取请求头参数
@ModelAttribute
若在方法上:优先于handler执行:
适用情况:若表单提交ID号,而handler想要数据库中的对应值,则可以在中间执行.
若在形参上:获取@ModelAttribute方法中返回的数据==如果没有,则会获取未经过@ModelAttribute处理的数据 ==
一个返回参数:利用返回值返回
多个返回参数:利用@ModelAttribute绑定handler中的形参
通过这个例子,我们可以推测,参数绑定也是利用Map的方式执行的
SessionAttribute
将本handler中的参数存入到Session中
默认配置视图解析器:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
REST的过滤器
映射URL绑定的占位符
REST:资源表现层转化。即将资源显示呈现
1:delete对应删除,get对应查询,post对应修改,put对应增加
2:返回的是基本页面即404,500
但是页面的基本提交方式只有get和post,所以为了能够提交delete和put页面,需要实现过滤器
过滤器:
1:将HiddenHttpMethodFIlter配置到web.xml文件中。 能将特殊的post请求转化为delete和put请求
2:当想要发送delete请求时,只需要发送一个含有name="_method"value="DELETE"的post请求
< form action="springmvc/testRest/1" method="post">
< input type="hidden" name="_method" value="DELETE">
< /form>
此时这个请求就是一个DELETE请求
3:验证:RequestMapping的method="RequestMapping.DELETE"进行验证
参数绑定
数据绑定要求请求参数名和方法中的参数名相同,或使用@RequestParam为方法参数起别名.
三种类型:
基本数据类型和String类型
JavaBean类型
集合类型
基本类型
SpringMVC将请求参数中的param=value中的value传递给控制器方法的param参数,例如:
<a href="account/findAccount?accountId=10">查询账户</a>
// 控制器类
@Controller
@RequestMapping(path = "/account")
public class HelloController {
@RequestMapping(path = "/findAccount")
public void findAccount(Integer accountId) {
// accountId = 10
// 方法体...
}
}
SpringMVC中会将10传给findAccount方法的accountID参数传递给HandlerAdapter执行
JavaBean类型的参数
级联映射
要想实现绑定,就必须实现其空参构造函数和所有属性的get,set方法
示例如下:
例如JavaBean类的定义如下:
public class Account implements Serializable {
private String username;
private Intger age;
private User user;
// 所有属性的getset方法...
}
public class User implements Serializable{
private String uname;
private Double umoney;
// 所有属性的getset方法...
}
则其对应的请求参数名如下:
<form action="account/updateAccount" method="post">
<label>名称</label><input type="text" name="username"><br/>
<label>年龄</label><input type="text" name="age"><br/>
<label>用户名</label><input type="text" name="user.uname"><br/>
<label>用户余额</label><input type="text" name="user.umoney"><br/>
<input type="submit" value="保存">
</form>
集合类型
对JavaBean类中的集合属性进行参数绑定,可以分为List类型的参数绑定和Set类型的参数绑定
对于List类型参数,其请求参数名为集合名[下标]
<input type="text" name="accounts[0].money"><br/>
对于Set类型参数,其请求参数名为集合名[键]
<input type="text" name="accountMap['one'].money"><br/>
自定义转化器
表单提交类型:字符串类型
方法参数:其他类型
所以赋值的时候需要转化,SpringMVC有携带默认的转换器Converter。当然我们也可以实现我们的自己的转换器Converter<String, T>。当需要String转换到T时,就会调用默认的转化器
// 自定义的类型转换器,完成从String类到Date类的转换
public class StringToDateConverter implements Converter<String, Date> {
public Date convert(String source) {
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date date = df.parse(source);
return date;
} catch (Exception e) {
throw new RuntimeException("类型转换错误");
}
}
}
在Spring容器配置bean.xml中加入如下配置:
<!-- 配置的类型转换器工厂 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<!-- 诸如我们自定义的类型转换器 -->
<bean class="cn.maoritian.utils.StringToDateConverter"/>
</set>
</property>
</bean>
注意:
当名字不同而想要绑定时:
@RequestParam注解: 为处理器方法参数起别名
<a href="testRequestParam?param1=value">测试requestParam注解</a>
处理器方法中给对应参数加上@RequestParam(name="param1")注解来接收参数
@RequestMapping("/testRequestParam")
public String handlerMethod(@RequestParam("param1") String username) {
// 方法体...
}
返回值处理
返回:String对象
会根据String值返回到对应的JSP页面
return “success”;即返回到success.jsp
返回:void
当前URL对应的JSP页面
或者利用重定向或者转发
(1)request.getRequestDispatcher()是请求转发,前后页面共享一个request ; 这个是在服务端运行的,对浏览器来说是透明的。客户端发送一次请求,URL地址相同
return “forward”:/WEB_INF/pages/success.jsp"不会经过视图解析器
(2)response.sendRedirect()是重新定向,前后页面不是一个request。而这个是在浏览器端运行的。相当于客户端发送两次请求,URL地址不同
程序都会在执行完该句的情况下继续向下执行,因此在必要的时候应该使用return终止该方法。并且在之后操作request都没有意义,request.getRequestDispatcher执行时会生成一个新的request,而response会重新定向。
return “redirect:/success.jsp”; 会经过视图解析器
返回:ModelAndView
public ModelAndView addObject(Object attributeValue): 向当前页面的ModelMap对象中添加属性
public void setViewName(@Nullable String viewName): 指定返回视图
异步加载和响应JSON数据
默认条件下,前端控制器会拦截静态资源(css,js,jq)。所以需要配置web.xml禁止拦截
因此我们需要在Spring容器配置bean.xml中使用< mvc:resources>标签声明该资源为静态资源,否则请求该资源会报404错误.该标签的属性如下:
配置下列文件夹下的资源为静态资源
<!-- 配置静态文件的路径于对应的URL -->
<!-- location属性必须是一个有效的目录,因此必须以 / 结尾 -->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**"/>
实现:
客户端页面:
<script>
// 页面加载,绑定单击事件
$(function () {
$("#btn").click(function () {
// 发送ajax请求
$.ajax({
// 配置请求参数
url: "user/testAjax",
contentType: "application/json;charset=UTF-8",
dataType: "json",
type: "post",
// 请求的json数据
data: '{"username":"myname","password":"mypassowrd","age":30}',
// 回调函数,处理服务器返回的数据returnData
success: function (returnData) {
// 我们假定服务器返回的是一个user对象,将其输出在控制台上
console.log(returnData); }
});
});
});
</script>
handler:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user) {
System.out.println(user);
user.setUsername("myName")
// 将user对象返回给前端页面
return user;
}
}
上述流程为:
1:客户端的data: '{“username”:“myname”,“password”:“mypassowrd”,“age”:30}'传入到服务器
2:handler中@RequestBody注解的对象接收数据,因为是一个user,@RequestBody将其封装
3:如果返回修改的user对象到,即return user。但是因为ajax页面接收的是json数据,所以需要@ResponseBody User,即在返回类型注解
文件上传
1:method为post
2:enctype为multipart/form-data
3:提供 type="file"的上传输入域
关于enctype的属性
一:application/x-www-form-urlencoded:
1:默认是application/x-www-form-urlencoded,键值对
2:如果action为get,则将表单数据编码为(name1=value1&name2=value2…),然后把这个字符串加到url后面,中间用?分隔
3:如果action为post,浏览器把form数据封装到http body中,然后发送到服务器。
二:text/plain:
表单以纯文本形式进行编码
三:multipart/form-data:
1:含有非文本内容,即含有文件(txt、MP3等)设置为multipart/form-data。
2:将表单中的数据变成二进制数据进行上传,所以这时候这时如果用request是无法直接获取到相应表单的值的
springmvc文件上传:
1:配置文件解析器,上传的请求先到达解析器,返回MultipartFile upload)
<!-- 配置文件解析器,其id是固定的,必须为multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置文件的最大尺寸 -->
<property name="maxUploadSize" value="10485760"/>
</bean>
2:handler通过@RequestParam(“fileParam”) MultipartFile upload获取需要上传的文件对象,之后只需要为文件对象指定地址即可
@Controller
@RequestMapping("/fileUpload")
public class FileUploadController {
@RequestMapping("/springMVC")
public String fileupload2(HttpServletRequest request, @RequestParam("fileParam") MultipartFile upload) throws Exception {
// 创建目录保存上传的文件
String path = request.getSession().getServletContext().getRealPath("/uploads/");
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
// 服务器中保存的文件名
String filename = UUID.randomUUID().toString().replace("-", "") + "_" + upload.getOriginalFilename();
// 上传文件
upload.transferTo(new File(path,filename));
return "success";
}
}