1. Controller方法(Handler)的返回值
1.1 返回ModelAndView
- 若处理器对请求处理过后,不仅要进行跳转,而且在跳转过程中还要传递数据,此时使用ModelAndView较为方便。
- 在控制器类中,处理客户端请求后,可以把需要响应到页面的数据和视图名字都封装到一个ModelAndView对象中,然后直接返回这个ModelAndView对象。
- 示例代码如下,将时间数据保存到ModelAndView对象,并传递到result.jsp页面。
@Controller
public class DefaultController {
/**
* 定义方法, 相当于以前Servlet中用于处理请求的方法
*/
@RequestMapping("gotoResult")
public ModelAndView gotoResult(ModelAndView modelAndView){
// 封装数据
modelAndView.addObject("nowDate",new Date());
//指定页面
modelAndView.setViewName("result");
return modelAndView;
}
}
1.2 返回字符串
- 直接返回逻辑视图名,数据使用Model和ModelMap封装;
- ModelAndView = ModelMap+ view(逻辑视图名);
- 现在直接将逻辑视图名以字符串形式return(文件名);
- Model接口方法 addAttribute(String key,Object value)存储键值对,将被存储到request域中,示例代码如下:
/**
* 返回字符串,返回视图逻辑名,文件名
* Model接口封装数据
* 键值对存储request域对象
*/
@RequestMapping("gotoResultModel")
public String gotoResultModel(Model model){
//封装数据
model.addAttribute("nowDate", new Date()+"====gotoResultModel");
//指定页面
return "result";
}
- ModelMap封装数据,方法addAttribute(String key,Object value)存储键值对,将被存储到request域中
/**
* 返回字符串,返回视图逻辑名,文件名
* ModelMap类封装数据
* 键值对存储request域对象
* ModelMap类有获取的方法,而Model接口没有
*/
@RequestMapping("gotoResultModelMap")
public String gotoResultModelMap(ModelMap modelMap){
//封装数据
modelMap.addAttribute("nowDate", new Date()+"====gotoResultModelMap");
//指定页面
return "result";
}
- 使用转发进行页面跳转
@RequestMapping("gotoResultForward")
public String gotoResultForward(ModelMap modelMap){
modelMap.addAttribute("nowDate",new Date()+"====gotoResult");
return "forward:/default/gotoResultModelMap.do";
}
- 使用重定向进行页面跳转
@RequestMapping("gotoResultRedirect")
public String gotoResultRedirect(ModelMap modelMap){
modelMap.addAttribute("nowDate",new Date()+"====gotoResult");
return "redirect:/default/gotoResultModelMap.do";
}
1.3 没有返回值
- request对象实现转发
/**
* 返回值为void类型, 使用Request对象 实现页面跳转(注意: 无法将SpringMVC 提供的Model, ModelMap封装的数据 请求转发到目标页面)
*/
@RequestMapping("gotoResultRequest")
public void gotoResultRequest(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过SpringMVC框架把封装数据到Request域中( 跳转页面的方式必须采用的是SpringMVC框架提交的方式, 才能把数据 传递过去 )
modelMap.addAttribute("nowDate", new Date()+"====gotoResultRequest");
//request.setAttribute("键", "值");
//指定页面,请求转发
request.getRequestDispatcher("/default/gotoResultModelMap.do").forward(request, response);
}
- response对象实现重定向
/**
* 返回值为void类型, 使用Response跳转页面 (注意: 无法将SpringMVC 提供的Model, ModelMap封装的数据 重定向到目标页面)
*/
@RequestMapping("gotoResultResponse")
public void gotoResultResponse(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过SpringMVC框架把封装数据到Request域中( 跳转页面的方式必须采用的是SpringMVC框架提交的方式, 才能把数据 传递过去 )
modelMap.addAttribute("nowDate", new Date()+"====gotoResultResponse");
//指定页面,重定向
//response.sendRedirect("http://localhost:8080/default/gotoResultModelMap.do");
response.sendRedirect(request.getContextPath()+"/default/gotoResultModelMap.do");
}
- response对象响应字符串
/**
* 直接使用response对象响应字符串
*/
@RequestMapping("gotoResultResponseSendString")
public void gotoResultResponseString(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().print("Hello MVC");
}
2. Json格式数据实现Ajax交互
- 交互:前端和后端的互动
- 前端传递json字符串到后台,后台通过@RequestBody注解,将json字符串转换为pojo对象
- @RequestBody注解作用:用于获取请求体(按照http协议进行一个完整的封装,往往都是由请求头+请求体等组成)内容,不适用于Get请求方式
- 后端返回对象,前端通过@ResponseBody注解直接接收到json格式的字符串
- @ResponseBody注解作用:该注解用于将Controller的方法返回的对象转换为json字符串返回给客户端
2.1 @RequestBody注解示例
- 前端index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
<%--导入js文件--%>
<script src="js/vue.js"></script>
<script src="js/axios-0.18.0.js"></script>
</head>
<body>
SpringMVC框架的进行 Ajax 交互
<fieldset>
<h4>Ajax 的Json数据</h4>
<div id="app">
<input type="button" @click="clickMe()" value="发送Ajax数据">
<%--使用插值表达式--%>
{{ userList }}
</div>
</fieldset>
</body>
</html>
<script>
<!-- 创建一个Vue对象 -->
new Vue({
el: '#app',
data:{
userList: []
},
methods:{
clickMe:function(){
var params = {id:1, username:'你好', sex:'男'};
//发起ajax
axios.post("/ajax/testAjax.do", params)
.then(response => {
//成功
//console.log(response.data);
this.userList = response.data
}).catch(error =>{
//失败
console.dir(error);
});
}
}
})
</script>
- 后端接收params 数据并转换成pojo对象,pojo类太简单了就不写了,后端代码如下:
@RequestMapping("ajax")
@Controller
public class AjaxController {
//测试Ajax的方法
@RequestMapping("testAjax")
public void testAjax(@RequestBody User user){
// 打印接收的数据
System.out.println("user = " + user);
}
}
2.2 @ResponseBody注解示例
前端代码与2.1中的index.jsp一致,后端代码如下,注意@RestController
中包含 @ResponseBody
和@Controller
两个注解
@RequestMapping("ajax")
@RestController
public class AjaxController {
//测试Ajax的方法
@RequestMapping("testAjax")
public List<User> testAjax(@RequestBody User user){
// 打印接收的数据
System.out.println("user = " + user);
// 准备给客户端浏览器返回的json数据
User user1 = new User();
user1.setId(2);
user1.setName("李四");
user1.setSex("男");
User user2 = new User();
user2.setId(3);
user2.setName("王五");
user2.setSex("女");
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
return list;
}
}
3. SpringMVC实现文件上传
前提:
- form表单请求方式必须是post
- 添加form表单的参数:enctype 多部件表单类型 enctype=“multipart/form-data”
- 引入依赖:commons-upload, commons-io
3.1 文件上传
3.1.1 引入依赖
<!-- 引入fileUpload会自动依赖commons-io -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
3.1.2 spring-mvc.xml 配置文件
<!-- 配置文件上传解析器 -->
<!-- id的值是固定的-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
3.1.3 页面配置
<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
<input type="file" name="uploadFile">
<input type="text" name="username">
<input type="submit" value="上传">
</form>
3.1.4 Controller层代码
@Controller
public class UploadController {
/**
* 本地上传
MultipartFile接口方法:
- String getOriginalFilename()获取上传文件名
- byte[] getBytes()文件转成字节数组
- void transferTo(File file)转换方法,将上传文件转换到File对象
*/
@RequestMapping("/upload")
public String upload(MultipartFile uploadFile, HttpServletRequest request){
//32位的随机内容的字符串
String uuid = UUID.randomUUID().toString().replace("-","");
//文件名称
String filename = uploadFile.getOriginalFilename();
System.out.println("filename = " + filename);
//文件上传
String realPath = request.getSession().getServletContext().getRealPath(request.getContextPath() + "/upload");
File path = new File(realPath, uuid+filename);
try {
uploadFile.transferTo(path);
} catch (IOException e) {
e.printStackTrace();
}
return "success";
}
}
3.2 跨服上传
3.2.1 引入依赖
<!--引入jersey服务器的包-->
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
<version>1.18.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18.1</version>
</dependency>
3.2.2 修改tomcat配置
注意:
- tomcat默认不能跨服上传的
- 在安装目录tomcat/conf/web.xml下修改
<!--需要添加的-->
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>
3.2.3 配置图片服务器
- 创建一个web项目
- 配置一个tomcat,与原来tomcat端口号不一致
- 在webapp目录下创建一个upload目录,空的文件夹不会编译,需要在upload目录添加(任意)一个文件
3.2.4 Controller代码
/**
* 跨服上传
MultipartFile接口方法:
- String getOriginalFilename()获取上传文件名
- byte[] getBytes()文件转成字节数组
*/
@Controller
public class UploadController {
@RequestMapping("/upload")
public String upload(MultipartFile uploadFile, HttpServletRequest request){
//32位的随机内容的字符串
String uuid = UUID.randomUUID().toString().replace("-","");
//文件名称
String filename = uploadFile.getOriginalFilename();
System.out.println("filename = " + filename);
//跨服务器上传
String serverUrl = "http://localhost:8081/upload";
//向服务器上传的客户端对象
Client client = Client.create();
WebResource resource = client.resource(serverUrl + "/" + uuid + filename);
//执行上传文件到 指定的服务器
//转出字节数组开始上传
try {
resource.put(String.class, uploadFile.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
return "success";
}
}