1 响应数据和结果视图
响应数据和结果视图
字符串
controller方法返回字符串可以指定逻辑视图名字,通过视图解析器,解析为一个jsp的物理视图地址。
比如:
@RequestMapping("/testReturnString")
public String testReturnString() {
System.out.println("AccountController 的 testReturnString 方法执行了。。。。");
return "success";
}
结果:
仔细看截图红框和代码直接的关系。
void
页面跳转,可以把原生的 HttpServletRequest 跟 HttpServletResponse 做入参数注入到目标方法中。servlet怎么用,现在就怎么用
适用场景:异步请求
返回的不是一个纯页面,可能就是一些简单数据。
代码:
jsp代码:
testVoid
java代码:
@Controller
@RequestMapping("/user")
public class userController{
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request,HttpServletRsponse response) throws Exception{
System.out.println("testVoid 方法执行");
//编写请求转发的程序 (手动写转发时 程序不会调用视图解析器 所以写路径要写全)
request.getRequstDispatcher("/WEB-INF/pages/success.jsp ").forward(request,response);
//如果是重定向
response.sendRedirect(request.getContextPath()+" /index.jsp ");
//如果是直接响应
//1 首先设置中文乱码
response.setCharaterEncoding("UTF-8");
response.setContenType("test/html;charset=UTF-8");
//2 直接响应的数据
response.getWriter().print("直接响应成功");
return;
}
}
ModelAndView
ModelAndView 是 SpringMVC 为我们提供的一个对象,无论返回值是什么,springmvc 都会把结果封装成一个 ModelAndView对象。该对象也可以用作控制器方法的返回值。也可以通过视图解析器跳转到某个页面。
ModelAndView 中有两个方法
addObject(String,Object);
封装数据,底层是把数据封装到了 request 域中
setViewName(String);
指定视图名称
适用场景:当Handler 执行完后,即有模型数据时,又有响应视图信息。
代码:
jsp代码:
testVoid
java代码:
@Controller
@RequestMapping("/user")
public class userController{
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
ModelAndView mv = new ModelAndView();
User user = new User();
user.setUsername("小凤");
user.setPassword("456");
user.setAge(30);
//把user对象存入到mv对象中,底层也会把user这个对象存到request域对象当中。
mv.addObject("user",user);
//想跳转到哪个页面。
mv.setViewName("success");
return mv;
}
}
success.jsp
执行成功
${user.username}
${user.password}
输出结果为:
如果用了关键字
forward
和redirect
进行页面跳转,那么视图解析器会失效,路径需要自己注意写全。
//请求转发
return "forward:/WEB-INF/pages/success.jsp";
需要注意的是,如果用了 formward:则路径必须写成实际视图 url,
不能写逻辑视图。 它相当于“request.getRequestDispatcher("url").forward(request,response)”。
使用请求 转发,既可以转发到 jsp,也可以转发到其他的控制器方法。
//重定向
return "redirect:/index.jsp";
它相当于“response.sendRedirect(url)”。需要注意的是,
如果是重定向到 jsp 页面,则 jsp 页面不 能写在 WEB-INF 目录中,否则无法找到。
@ResponseBody 响应 json 数据
作用: 该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的 数据如:json,xml 等,通过 Response 响应给客户端。
- DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而 不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置
- mvc:resources标签配置不过滤
1. location元素表示webapp目录下的包下的所有文件
2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
1 创建一个js的文件夹 然后引入一个jQuery.min.js
文件。
2 在页面当中引入这个文件,新建一个请求按钮 ,绑定单击事件:
<%@page cintentType = "text/html;charset=UTF-8 " language="java"%>
Title
//引入jQuery文件
//页面加载 绑定单击事件
$(function(){
$("#btn").clinck(function(){
//发送ajax请求
$.ajax({
//编写json格式:设置属性和值。
//url :请求路径
//contentType:指定发送至服务器内容的编码格式。
//data:发送到服务器的数据。
//dataType:预期服务器返回的数据类型。
//type:请求方式
//success:请求成功后回调函数
url:"user/testAjax",
contentType:"application/json;charset:utf-8",
data:'{" username":"hehe ","password":"123"}',
dataType:"json",
type:"post",
success:function(data){
//这里的data是服务器响应的json数据
}
});
});
});
//新建请求按钮
3 在springmvc.xml中配置上方的拦截器。
4 模拟异步请求响应
@RequstMapping("/testAjax")
public @RequestBody user testAjax(@RequestBody User user){
System.out.println("testAjax执行");
//客户端发送ajax的请求 传的是json字符串 后端把json字符串封装到user对象中,作相应,模拟查询数据库
user.setUsername("haha");
user.setAge(40);
//作相应
return user;
}
响应数据(json数据)
@ResponseBody 响应 json 数据
@ResponseBody 修饰目标 Handler 方法
springmvc 会把返回的对象或者集合转换成 json 串
如果返回的是普通字符串,那么就是字符串
前提:必须导入 jackson 的三个 jar 包(版本要求在 2.7.0 以上)
如果报 415 异常,很有可能是没有导入 jackson 依赖。
json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包
com.fasterxml.jackson.core
jackson-databind
2.9.0
com.fasterxml.jackson.core
jackson-core
2.9.0
com.fasterxml.jackson.core
jackson-annotations
2.9.0
6、文件上传
文件上传的回顾
- 导入文件上传的jar包
commons-fileupload
commons-fileupload
1.3.1
commons-io
commons-io
2.4
- 编写文件上传的JSP页面
文件上传
- 编写文件上传的Controller控制器
/**
* 文件上传
*/
@RequestMapping(value="/fileupload")
public String fileupload(HttpServletRequest request) throws Exception {
// 先获取到要上传的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
// 创建File对象,一会向该路径下上传文件
File file = new File(path);
// 判断路径是否存在,如果不存在,创建该路径
if(!file.exists()) {
file.mkdirs();
}
// 创建磁盘文件项工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 解析request对象
List list = fileUpload.parseRequest(request);
// 遍历
for (FileItem fileItem : list) {
// 判断文件项是普通字段,还是上传的文件
if(fileItem.isFormField()) {
}else {
// 上传文件项
// 获取到上传文件的名称
String filename = fileItem.getName();
// 上传文件
fileItem.write(new File(file, filename));
// 删除临时文件
fileItem.delete();
}
}
return "success";
}
2. SpringMVC传统方式文件上传
SpringMVC框架提供了
MultipartFile
对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同。代码如下
/**
* SpringMVC方式的文件上传
*/
@RequestMapping(value="/fileupload2")
public String fileupload2(HttpServletRequest request,MultipartFile upload) throws Exception {
System.out.println("SpringMVC方式的文件上传...");
// 先获取到要上传的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
// 创建File对象,一会向该路径下上传文件
File file = new File(path);
// 判断路径是否存在,如果不存在,创建该路径
if(!file.exists()) {
file.mkdirs();
}
// 获取到上传文件的名称
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
// 把文件的名称唯一化
filename = uuid+"_"+filename;
// 上传文件
upload.transferTo(new File(file,filename));
return "success";
}
- 配置文件解析器对象
3. SpringMVC跨服务器方式文件上传
- 搭建图片服务器
- 根据文档配置tomcat9的服务器,现在是2个服务器
- 导入资料中day02_springmvc5_02image项目,作为图片服务器使
- 实现SpringMVC跨服务器方式文件上传
1 导入开发需要的jar包
com.sun.jersey
jersey-core
1.18.1
com.sun.jersey
jersey-client
1.18.1
2 编写文件上传的JSP页面
跨服务器的文件上传
3 编写控制器
/**
* SpringMVC跨服务器方式的文件上
*/
@RequestMapping(value="/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception {
System.out.println("SpringMVC跨服务器方式的文件上传...");
// 定义图片服务器的请求路径
String path = "http://localhost:9090/day02_springmvc5_02image/uploads/";
// 获取到上传文件的名称
String filename = upload.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
// 把文件的名称唯一化
filename = uuid+"_"+filename;
// 向图片服务器上传文件
// 创建客户端对象
Client client = Client.create();
// 连接图片服务器
WebResource webResource = client.resource(path+filename);
// 上传文件
webResource.put(upload.getBytes());
return "success";
}
注意:跨服务器上传文件时,会抛出一个异常,状态码为403
解决方案如下:在 tomcat/conf/web.xml 找到
default
org.apache.catalina.servlets.DefaultServlet
debug
0
listings
false
readonly
false
1
异常处理机制
当程序出现错误的时候,会一层层的向上抛出,最后到前端控制器这里反馈给浏览器,此时如果不在前端控制器上做处理,那么错误就会原封不动的返回给浏览器,这样用户感受很不好,所以我们的异常处理指的是:在前端控制器里配置一个异常处理组件来处理异常,只要有异常,被它捕获以后会给浏览器返回一个友好的提示错误页面。
编辑自定义异常类和错误页面
/**
* 自定义异常类
*/
public class CustomException extends Exception {
private String message;
public CustomException(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
jsp 页面:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
执行失败
执行失败!
${message }
定义一个异常处理类实现 HandlerExceptionResolver 接口,重写抽象方法
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
// 获取到异常对象
SysException e = null;
if(ex instanceof SysException){
e = (SysException)ex;
}else{
e = new SysException("系统正在维护....");
}
// 创建ModelAndView对象
ModelAndView mv = new ModelAndView();
mv.addObject("errorMsg",e.getMessage());
mv.setViewName("error");
return mv;
}
在 springmvc.xml 配置文件中配置异常处理器bean
例如:
8、拦截器
过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。
过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦 截的。
它也是 AOP 思想的具体应用。
自定义拦截器 实现 HandlerInterceptor 接口
/**
* 自定义拦截器
*/
public class MyInterceptor1 implements HandlerInterceptor {
/**
* 预处理,controller方法执行前 执行
* return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
* return false 不放行,不会执行controller的方法
* 通常用来做 权限拦截
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor1执行了...前1111");
return true;//放行
}
/**
* 后处理方法,controller方法执行后,success.jsp 执行之前 执行
* 通常用来 改变响应视图
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor1执行了...后1111");
}
/**
* success.jsp页面执行后,该方法会执行
* 通常用来 释放资源
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor1执行了...最后1111");
}
}
在 springmvc.xml 配置文件中配置拦截器