SpringMVC
视图解析
请求处理方法(controller方法)执行完成后,最终返回一个 ModelAndView 对象,即使出现异常也会返回一个 ModelAndView 对象。对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象,它包含了逻辑名和模型对象的视图,由视图解析器解析视图,然后,进行页面的跳转。
Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP ,也可能是 Excel、JFreeChart等各种表现形式的视图
视图View
视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户
1. 将数据存放到域中 request.setAttribute(name,value)
2. 转发|重定向 rd.forward(request,response);
为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口
视图对象由视图解析器负责实例化。由于视图是无状态的,所以他们不会有线程安全的问题
常用的视图实现类
转发视图:InternalResourceView
转发视图:JstlView 需导入Jstl的jar包,适配器会自动调用此解析器,此解析器继承了InternalResourceView
若使用 JSTL 的 fmt 标签则需要在 SpringMVC 的配置文件中装配标准资源文件bean
重定向视图:RedirectView
一般情况下,控制器方法返回字符串类型的值会被当成逻辑视图名处理
如果返回的字符串中带 forward: 或redirect:前缀时,SpringMVC 会对他们进行特殊处理:将 forward: 和 redirect: 当成指示符,其后的字符串作为 URL 来处理
在返回值中 return "redirect:/success_redirect.jsp";解析器会自动重定向到此页面,不需在前面加工程路径名RedirectView会自动帮我们追加上
注意
转发:访问 WEB-INF 下路径时只允许当前请求为GET或POST请求模式的才能转发成功,(也就是浏览器只支持GET、POST请求的转发)默认携带当前的请求方式发起转发请求。
访问 Controller 内部路径时必须加上前缀 forward: 同样携带当前的请求方式发起请求,必须有对应的请求方式的路径
重定向:必须先加上前缀 redirect: 访问 WEB-INF 下的路径不被允许,默认用 GET 方法发起新的请求。
访问 Controller 内部路径时同样只能重定向到GET请求方式的路径
视图解析器ViewResolver
SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 SpringMVC 上下文中配置一种或多种解析策略,并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。通过反射原理
视图解析器的作用比较单一:将逻辑视图解析为一个具体的视图对象
url= getPrefix() + viewName + getSuffix()
每个视图解析器都实现了 Ordered 接口并开放出一个 order 属性,可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高。
JSP 是最常见的视图技术,可以使用默认的 InternalResourceViewResolve 作为视图解析器
BeanNameViewResolver:将逻辑视图名解析为一个 Bean , Bean 的 id 等于逻辑视图名
Spring表单标签
SpringMVC 的表单标签可以实现将模型数据中的属性和 HTML 表单元素相绑定,以实现表单数据更便捷编辑和表单值的回显
引入标签库
form 标签
标签 可以通过 modelAttribute 属性指定绑定的模型属性,若没有指定该属性,则默认从 request 域对象中读取 command 属性的表单 bean,如果该属性值也不存在,则会发生错误。SpringMVC 提供了多个表单组件标签用以绑定表单字段的属性值,如 (同html标签中 input type="text"),它们的共有属性:
path:表单字段,对应html元素的name属性,支持级联属性
htmlEscape:是否对表单值的 HTML 特殊字符进行转换,默认值为 true
cssClass:表单组件对应的 CSS 样式类名
cssErrorClass:表单组件的数据存在错误时,采取的 CSS 样式
form:input、form:password、form:hidden、form:textarea:对应 HTML 表单的 text、password、hidden、textarea 标签
form:radiobutton:单选框组件标签,当表单 bean 对应的属性值和 value 值相等时,单选框被选中
form:radiobuttons:单选框组标签,用于构造多个单选框
items:可以是一个 List、String[] 或 Map
itemValue:指定 radio 的 value 值。可以是集合中 bean 的一个属性值
itemLabel:指定 radio 的 label 值
delimiter:多个单选框可以通过 delimiter 指定分隔符
form:checkbox:复选框组件。用于构造单个复选框
form:checkboxs:用于构造多个复选框。使用方式同 form:radiobuttons 标签
form:select:用于构造下拉框组件。使用方式同 form:radiobuttons 标签
form:option:下拉框选项组件标签。使用方式同 form:radiobuttons 标签
form:errors:显示表单组件或数据校验所对应的错误
:显示表单所有的错误
:显示所有以 user 为前缀的属性对应的错误
:显示特定表单对象属性的错误
//修改功能需要增加绝对路径,相对路径会报错,路径不对LastName:
Email:
Gender:
Dept:
通过jQuery转换为DELETE请求
REST风格代码,要求删除功能,必须以DELETE方式提交。解决方案
1. 准备一个以DELETE方式提交的form表单
2. 通过单击事件为准备好的form表单action属性赋值。
3. 触发表单的submit事件
$(function(){
$(".delete").click(function(){var href = $(this).attr("href");
$("form").attr("action",href).submit();return false;
});
});
SpringMVC 处理静态资源
若将DispatcherServlet 请求映射配置为/, 则Spring MVC 将捕获WEB 容器的所有请求, 包括静态资源的请求, SpringMVC 会将他们当成一个普通请求处理, 因找不到对应处理器将导致错误。从而无法加载静态资源
解决: 需要在 SpringMVC 的配置文件中配置 它将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是静态资源的请求,就会由此处理器处理
并且还需要配置,因为只配置上面一个所有请求又全部只由默认处理器来处理请求了
底层原理:Tomcat解析Servlet优先级问题
程序员定义的 Servlet优先级大于Tomcat自己的Servlet
URL中default-servlet配置 "*.jsp" 大于 "/" 的配置。
处理JSON和下载
HttpMessageConverter
HttpMessageConverter 是 Spring3.0 新添加的一个接口,负责将请求信息转换为一个对象(类型为T),将对象(类型为T)输出为响应信息
当控制器处理方法使用到 @RequestBody/@ResponseBody 或 HttpEntity/ResponseEntity 时, Spring 首先根据请求头或响应头的 Accept 属性选择匹配的 HttpMessageConverter, 进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter, 若找不到可用的 HttpMessageConverter 将报错 406
HttpMessageConverter 可将请求信息转化并绑定到(controller)处理方法的入参中或将响应结果转为对应类型的响应信息
SpringMVC处理 json
1) jackson-annotations-2.1.5.jar
jackson-core-2.1.5.jar
jackson-databind-2.1.5.jar
2)需要在配置文件设置
如此可将适配器AnnotationMethodHandlerAdapter升级为:RequestMappingHandlerAdapter 而 RequestMappingHandlerAdapter 适配器中存在MappingJackson2HttpMessageConverter
3)@RequestBody / @ResponseBody在处理方法上进行标注
@RequestBody:是将Http请求正文插入到处理方法中,修饰目标方法的入参
@ResponseBody:是将内容或对象作为Http响应正文返回去
将user对象转为json对象返回,注意ajax设置dataType:"json"类型
@ResponseBody
@RequestMapping(value= "/json",method =RequestMethod.GET)publicUser json(String string){returnuser;
}
异步请求
$("#username1").change(function() {var username = $("#username1").val();var dat ={"username":username,"_method":"PUT",
};
$.ajax({
url:"${pageContext.request.contextPath}/login",
type:"POST",
data:dat,
dataType:"json",
success:function(data) {
alert(data.name);
},
error:function() {
alert("请求失败");
}
});
});
HttpEntity作为处理方法的入参获取文件大小请求头等
ResponseEntity作为处理方法的返回值,返回客户端要下载的文件资源,实现文件下载功能
下载
@RequestMapping(value = "/downLoad",method =RequestMethod.GET)public ResponseEntity testDownLoad(HttpServletRequest request,HttpServletResponse response) throwsIOException {
ResponseEntity responseEntity = null;//1.获取到download文件的真实路径(推荐先放在项目根目录下测试_downLoad为文件名)
String path = request.getServletContext().getRealPath("/downLoad");//在请求体中获取文件名
String fileName = request.getParameter("fileName");//2.通过真实文件路径创建File对象(File.separator为当前系统文件分隔符)
File file = new File(path + File.separator +fileName);//3.创建文件输入流,将要下载的文件读取到程序中
FileInputStream fileInputStream = newFileInputStream(file);byte[] bytes = new byte[fileInputStream.available()];//将文件一次性全部读取到bytes中
fileInputStream.read(bytes);//解决 文件名 中文乱码问题
String header = request.getHeader("User-Agent");if(header != null && header.contains("Firefox")) {
fileName= "=?utf-8?B?"+new BASE64Encoder().encode(fileName.getBytes("utf-8"))+"?=";
}else{
fileName= URLEncoder.encode(fileName, "UTF-8");
}//创建响应头
HttpHeaders httpHeaders = newHttpHeaders();
httpHeaders.add("Content-Disposition", "attachment; filename="+fileName);//返回资源(HttpStatus.OK=200)
responseEntity = new ResponseEntity<>(bytes, httpHeaders, HttpStatus.OK);
fileInputStream.close();returnresponseEntity;
}
文件上传
Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的 MultipartResolver 实现的。实现类:CommonsMultipartResolver
Spring MVC 上下文中默认没有装配 MultipartResovler,因此默认情况下不能处理文件的上传工作,需在上下文中配置 MultipartResolver
配置 MultipartResolver
defaultEncoding: 必须和用户 JSP 的 pageEncoding 属性一致,以便正确解析表单的内容,为了让 CommonsMultipartResolver 正确工作,必须先将 Commons-fileupload 及 Commons-io 的jar 包添加到类路径下。
MultipartResolver 用于处理文件上传,当收到请求时 DispatcherServlet 的 checkMultipart() 方法会调用 MultipartResolver 的 isMultipart() 方法判断请求中是否包含文件。如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest (继承了 HttpServletRequest) 对象中,最后传递给 Controller
上传文件
需上传文件:
@RequestMapping(value = "/upLoad",method =RequestMethod.POST)public String upLoad(@RequestParam("file")MultipartFile multipartFile,HttpServletRequest request) throwsIOException {//1.获取upload的真实路径
String path = request.getServletContext().getRealPath("/upLoad");//如果此路径不存在则创建此目录
File file1 = newFile(path);if(!file1.exists()){
file1.mkdir();
}//2.获取要上传的文件名
String filename =multipartFile.getOriginalFilename();//3.创建上传file
File file = new File(path + File.separator +filename);//4.实现文件上传
multipartFile.transferTo(file);return "home";
}
多文件上传