第一章:响应数据和结果视图
1.Map,Model,ModelMap 隐形参数的作用和关系(重点,用的多)
◆ 使用Map传递页面数据
◆ 使用Model传递页面数据
◆ 使用ModelMap传递页面数据
总结:以上三个隐形参数传过来的是同一个实现类对象:BindingAwareModelMap,底层都会把键值对数据放到request作用域中.
2. 控制层方法的(Controller)返回值分类
1. 返回字符串
Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析为物理视图的地址。(返回字符串都会
交给视图解析器来进行解析)
public String saveStudent(Student stu) { System.out.println(stu); // 编写控制逻辑 return "success"; //返回的字符串,会交给视图解析器,平凑成完整的界面地址,返回到中央拦截器(DispatcherServlet),再跳转到平凑出来的界面 }
2. 返回值为void,也会经过视图解析器,只能逻辑视图名时url的名字
@RequestMapping("/save2") public void saveStudent(Student stu) { System.out.println(stu); } 物理视图名是save2.jsp
这样简单的写会报错,所以返回
3. 使用request转向页面 (了解)
@RequestMapping("/save2") public void saveStudent(Student stu,Map<String, Student> map,HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { System.out.println(stu); //map.put("stu", stu); request.setAttribute("stu", stu); request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response); }
总结:使用request进行页面的转发是不会经过视图解析器的
4. 使用response重定向页面(了解)
@RequestMapping("/save2")
public void saveStudent(Student stu,Map<String, Student> map,HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println(stu);
request.setAttribute("stu", stu);
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
总结:使用重定向进行页面的跳转是不会经过视图解析器的
5. 使用response获得输出流输出页面内容(了解)
@RequestMapping("/save3")
public void saveStudent(Student stu,HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
System.out.println(stu);
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().println(stu);//传递到界面
}
总结:通过输出流进行页面内容输出是不会经过视图解析器的
6. 返回值ModelAndView(重点)--即绑定数据模型,又绑定逻辑视图名
@RequestMapping("/find")
public ModelAndView findStudent(Student stu) throws ServletException, IOException {
ModelAndView mv = new ModelAndView();
mv.addObject("stu", stu);
mv.setViewName("success");//绑定逻辑视图名
return mv;
}
3.重定向和转发
◆ 转发
@RequestMapping("/find2")
public String findStudent2(Student stu,Model model) throws ServletException, IOException {
model.addAttribute("stu", stu);
return "forward:/WEB-INF/pages/success.jsp";
}
不经过视图解析器,使用的是同一个request对象
◆ 重定向
@RequestMapping("/find2") public String findStudent2(Student stu,Model model) throws ServletException, IOException { model.addAttribute("stu", stu); return "redirect:/index.jsp"; }
不经过视图解析器,使用的是同一个request对象
4.ResponseBody响应json数据(重点掌握)
◆ DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而 不
能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
◇ mvc:resources标签配置不过滤
○ location元素表示webapp目录下的包下的所有文件
○ mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
<!-- 设置静态资源不过滤 --> <mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 --> <mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 --> <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->
◆ 使用@RequestBody获取请求体数据
界面的ajax
$(function(){
$("#btn_send").click(function(){
$.ajax({
"url":"student/show",
"contentType":"application/json;charset=UTF-8",
"data":JSON.stringify({"id":$("#id").val(),"name":$("#name").val(),"age":$("#age").val(),"address":$("#address").val()}),
"dataType":"json",
"type":"post",
"success":function(data){
alert(data);
}
});
})
})
注意点: ajax发送过去的是json格式的字符串,不能直接json对象传递,可以使用
JSON.stringify(json对象)来进行转换成字符串
先使用@RequestBody注解把json的字符串转换成JavaBean的对象
再使用@ResponseBody注解把JavaBean对象转换成json字符串,直接响应
@RequestMapping("/testJson")
@ResponseBody
public Student testJson(@RequestBody Student stu) {
System.out.println(stu);
return stu;
}
注意点:@RequestBody得到请求内容,也就是json字符串,把json类型的数据自动和body内的属性进行值绑定
@ResponseBody 可以修饰类和修饰方法,修饰类,代表这个类的所有方法都会放回json字符串,全局设置
5.json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包 (使用@ResquestBody 需要导入这三个jar)
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency>
6.SpringMVC实现文件上传
1. 导入jar包
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
2. 编写页面
<form action="user/upload" method="post" enctype="multipart/form-data"> <input type="file" name="upload"> <button type="submit" id="btn_send">上传</button> </form>
3. 控制器方法的实现
package com.hwua.controller;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
@RequestMapping("/user")
@Controller
public class FileController {
@RequestMapping("/upload")
public ModelAndView fileUpload(HttpServletRequest request,MultipartFile
upload) {
ModelAndView mv = new ModelAndView();
//设置要上传文件的目录
String path = request.getServletContext().getRealPath("/upload");
//假如目录不存在,先创建要保存上传文件的目录
File file = new File(path);
if(!file.exists()) {
file.mkdirs();//创建目录
}
String fileName = upload.getOriginalFilename();//得到上传文件的名字
String uuid = UUID.randomUUID().toString().toUpperCase();//得到唯一的一串字符串
fileName = uuid+"_"+fileName;//拼成唯一的文件名
try {
upload.transferTo(new File(file,fileName));
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
mv.addObject("info", "上传失败!");
}//上传文件
mv.addObject("info", "上传成功!");
mv.setViewName("success");
return mv;
}
}
7.SpringMVC异常处理
1. 当异常一级级往上抛,到前端控制器DispatcherServlet都不处理的话,那么错误信息就会提交给用户界面,这种界面是不友好的.
2. 解决方案,一级级往上抛,抛到DispatcherServlet的时候,交给异常处理器对象来统一进行异常处理.最后把异常信息页面转发给用户.
操作流程:
第一步 自定义一个异常类,用来处理所有抛出的异常
package com.hwua.exception; public class SysErrorException extends Exception { private String message;// 保存自定义的异常信息 public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public SysErrorException(String message) { super(); this.message = message; } }
第二步 定义一个异常处理器类 实现HandlerExecptionResolver
package com.hwua.exceptionhandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import com.hwua.exception.SysErrorException;
public class SysErrorExceptionHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
SysErrorException se =null;
//获取异常类对象
if(se instanceof SysErrorException) {
se=(SysErrorException)ex;
}else {
se = new SysErrorException("错误,请联系管理员"+ex.getMessage());
}
ModelAndView mv = new ModelAndView();
mv.addObject("msg", se.getMessage());
mv.setViewName("error");
return mv;
}
}
第三步 在spring配置文件中配置异常处理器类,只要配置了,那么当前端控制接收到控制层抛出的异常,它就会交给异常处理器来进行统一处理.
<!--配置一个异常处理器对象 --> <bean id="sysErrorExceptionHandler" class="com.hwua.exceptionhandler.SysErrorExceptionHandler"></bean>