1、GET、POST以外的请求处理
GET、POST可以直接通过浏览器发送请求,但是HTTP协议里面还有PUT、DELETE之类的请求,浏览器无法直接发送的。
浏览器可以通过两种方式发送PUT、DELETE之类的请求:
1)使用jQuery,$.ajax({ ... } );
①MethodController.java
②a.jsp
<body>
<button οnclick="sendPut()">PUT请求</button>
<button οnclick="sendDelete()">DELETE请求</button>
<button οnclick="sendPost()">POST请求</button>
</body>
<script type="text/javascript">
var sendPut = function(){
$.ajax({
url:"${pageContext.request.contextPath}/hello/method",
method:"PUT",
success:function(data){
console.log(data);
}
});
};
var sendDelete = function(){
$.ajax({
url:"${pageContext.request.contextPath}/hello/method",
method:"DELETE",
success:function(data){
console.log(data);
}
});
};
var sendHead = function(){
$.ajax({
url:"${pageContext.request.contextPath}/hello/method",
method:"HEAD",
success:function(data){
console.log(data);
}
});
};
</script>
③测试:
i.PUT
ii.DELETE
iii.Head
2)使用隐藏的input作为method参数,本质上是POST请求,到了服务器的时候通过过滤器获取method作为请求方法的判断。
①页面上需要一个隐藏输入框
<input type=”hidden” name=”_method” value=”PUT”/>
b.jsp
<body>
<button οnclick="sendPut()">PUT请求</button>
<button οnclick="sendDelete()">DELETE请求</button>
<button οnclick="sendPost()">POST请求</button>
<button οnclick="sendHead()">Head请求</button>
</body>
<form id="testForm" action="${pageContext.request.contextPath}/hello/method" method="post" style="display: none">
<input name="_method">
</form>
<script type="text/javascript">
var sendPut = function(){
$("#testForm input[name='_method']").val("PUT");
$("#testForm").submit();
};
var sendDelete = function(){
$("#testForm input[name='_method']").val("DELETE");
$("#testForm").submit();
};
var sendPost = function(){
$("#testForm input[name='_method']").val("POST");
$("#testForm").submit();
};
var sendHead = function(){
$("#testForm input[name='_method']").val("HEAD");
$("#testForm").submit();
};
</script>
②在web.xml文件中,增加一个Spring提供的过滤器,获取请求参数里面的_method来判断是执行哪个操作。
org.springframework.web.filter.HiddenHttpMethodFilter
2、文件上传、下载
1)文件上传
①浏览器选择文件上传,表单的enctype要设置为multipart/form-data
②在web.xml文件中,配置DispatcherServlet的servlet元素中,增加<multipart-config/>标签,表示支持文件上传。
③方法参数使用MultipartFile作为数据类型接收上传的文件,调用service层保存文件到硬盘及相关信息至数据库。
save方法:
@Override
public void save(MultipartFile file) {
if (!dir.exists()) {
dir.mkdirs();
}
String fileName = UUID.randomUUID().toString();
File target = new File(dir, fileName);
try {
Files.copy(file.getInputStream(), target.toPath());
} catch (IOException e) {
throw new RuntimeException();
}
// 保存文件信息到数据库
FileInfo info = new FileInfo();
info.setContentLength(file.getSize());
info.setPath(target.getAbsolutePath());
System.out.println("=======" + file.getName() + "===========");
System.out.println("=======" + file.getOriginalFilename() + "===========");
info.setName(file.getOriginalFilename());
info.setContentType(file.getContentType());
try {
fileDao.save(info);
} catch (Exception e) {
// 如果在业务逻辑层里面捕获事务的异常,发现无法捕获的时候
// 需要在dao里面单独创建一个子事务
// 出现异常,表示文件信息保存失败,要把文件删除
target.delete();
throw new RuntimeException();
}
}
2)文件下载
①在列表页面,点击【下载】按钮,把文件信息的id作为路径参数传递给控制器。
②在业务逻辑层里面,根据路径参数中的id,查询文件信息,返回到控制器
③控制器的方法返回值类型为ResponseEntity<byte[]>,表示响应的内容完全自定义
3)测试
①打开列表页面
②上传文件
数据库:
磁盘:
3、返回JSON和XML数据
Spring支持HTTP的消息转换器,能够支持请求消息、响应消息的【内容协商式】自动转换。
内容协商:客户端需要什么样的数据,SpringMVC自动适应。
需要在mvc:annotation-driven配置里面增加【消息转换器】的配置。
还可以通过HTTP请求头中的【Accept】头来适应服务器返回的数据类型。
1)-servlet.xml中消息转换器配置:
2)控制器。方法test将一个集合当成响应体返回
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping
@ResponseBody
public List<User> test() {
List<User> list = new LinkedList<>();
System.out.println("======================");
User user = new User();
user.setAge(10);
user.setName("老十");
user.setBirthday(new Date());
list.add(user);
user = new User();
user.setAge(15);
user.setName("十五");
user.setBirthday(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 365));
list.add(user);
user = new User();
user.setAge(50);
user.setName("五十");
user.setBirthday(new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 365 * 2));
list.add(user);
return list;
}
}
3)测试
①json格式
②xml格式
4、国际化
1)需要在Spring配置文件中配置messageSource负责读取资源文件。
2)增加localeResolver用来根据请求参数,自动设置语言,存储的目标可以是Cookie、也可以是Session里面!
① CookieLocaleResolver 把语言存储在Cookie里面
② SessionLocaleResolver 把语言存储在Session里面
3)增加一个拦截器,用来设置语言。并且需要一个Action控制在设置语言以后跳转到哪个页面!
4)在JSP页面需要用到语言的时候,要使用 fmt:setLocale 标签/spring标签获取语言,并且设置到JSP页面。
5)控制器:
5)测试
5、Spring标签库分为Spring JSP 标签和Spring-Form JSP标签
6、表单验证
1)使用Spring自定义Validator对象,不需要引入其他的jar文件
①在Controller里面使用 @InitBinder 设置Validator的实现类对象
②在Validator的实现类里面,需要对要验证的属性一个个进行判断
@InitBinder
public void validate(WebDataBinder binder){
binder.setValidator(new Validator(){
@Override
public boolean supports(Class<?> clazz) {
// 表示User是clazz的一个实例
// User.class == clazz
// User.class就是我们要验证的实际类型
//isAssignableFrom:the boolean value indicating whether objects of the type cls can be assigned to objects of this class
return User.class.isAssignableFrom(clazz);
}
@Override
public void validate(Object target, Errors errors) {
//target与supports中的clazz类型是一样的
User user = (User)target;
if (user.getName() == null || user.getName().equals("")) {
// 没有传入name
// 错误信息,通常和输入框的name相同,也可以不同!
errors.rejectValue("name", "xxxx", "姓名必须填写");
}
if (user.getAge() < 1 || user.getAge() > 120) {
errors.rejectValue("age", "yyyy", "年龄必须是1~120之间");
}
}
});
}
③在Controller的处理方法(Action方法)参数列表里面,增加Errors类型的属性,用来接收验证错误信息。在方法开始的时候,需要判断:是否有错误,如果有错误需要自己返回到提示页面。同时参数需要使用 @Validated 注解。
④在JSP页面,使用spring的form标签库,显示错误信息。
<form:form method="POST">
<input name="name" value="${param.name}" />
<form:errors path="name" />
<input name="age" value="${param.age}" />
<form:errors path="age" />
<button type="submit">提交</button>
</form:form>
测试:
2)使用JSR-303规定的注解
①需要引入hibernate-validator.jar文件
加入4个jar包
②需要验证的类型里面的属性,使用Hibernate-validator(org.hibernate.validator)的注解标注要验证。
③在Controller的处理方法(Action方法)参数列表里面,增加Errors类型的属性,用来接收验证错误信息。在方法开始的时候,需要判断:是否有错误,如果有错误需要自己返回到提示页面。同时参数需要使用 @Valid 注解。
④在JSP页面,使用spring的form标签库,显示错误信息。
3)国际化
①对第一个例子进行国际化
i.在中文的属性文件加上:
ii.在英文的属性文件加上:
iii.测试
②对第二个例子进行国际化
i.在中文的属性文件加上:
ii.在英文的属性文件加上:
iii.测试
注意:
1.form:errors 标签,必须放到SpringMVC的form标签里面。
2.验证的结果,往往都是基于国际化的【codes】来查找提示信息,虽然有默认信息,但是依然建议加上国际化。
控制台打印信息:
ps:
@Validated 是只用Spring Validation 校验机制使用
@Valid是使用Hibernate Validator 的时候使用