JavaWeb进阶修炼手册33---核心框架:SpringMVC(二)

1. 今日内容

2. 响应数据和结果视图

2.1 控制器方法的返回值分类

2.1.1 字符串

controller 方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
例子:
在这里插入图片描述

2.1.2 void

方法没有返回值,默认情况下,会以该方法的虚拟路径到视图解析器中找物理地址,一般都不会存在,然后报错。
一般我们这样用:
在这里插入图片描述

2.1.3 ModelAndView(返回字符串底层调用的是ModelAndView)

ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
在这里插入图片描述
在这里插入图片描述

2.2 转发和重定向

下面两种方式不能用视图解析器解析,所以要写绝对路径,/代表项目根路径,即从项目名开始(包括项目名)。

2.2.1 forward 转发

在这里插入图片描述

2.2.2 Redirect 重定向

在这里插入图片描述
注意:重定向的jsp文件不能写在WEB-INF目录中,否则无法找到。

2.3 ResponseBody 响应 json 数据

2.3.1 静态资源不能被引用

DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而 不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置 :

  1. location元素表示webapp目录下的包下的所有文件
  2. 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 -->

2.3.2 将json数据封装成JavaBean对象

导入下面的jar包(必须导入jar包,不然会报运行错误)然后使用@RequestBody User user,会自动封装成User对象。
导入的jar包如下:

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.9.10</version>
</dependency>

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-core</artifactId>
   <version>2.9.10</version>
</dependency>

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-annotations</artifactId>
   <version>2.9.10</version>
</dependency>
<script>
  $(function () {
        $("#btn").click(function () {
            $.ajax({
                url:"hello/sayHello",
                type:"post",
                data:JSON.stringify({"username":"zhang", "password":"123"}),
                contentType:"application/json",
                dataType:"json",
                success:function(){
                    
                }
            });
        });
    });
</script>


@RequestMapping("/sayHello")
public String sayHello(@RequestBody User user){
     System.out.println(user);
     return "success";
}

2.3.3 ResponseBody 响应 json 数据

@Response注解方法的返回值,将JavaBean对象转为json对象。
如下:

<script>
   $(function () {
        $("#btn").click(function () {
            $.ajax({
                url:"hello/sayHello",
                type:"post",
                data:JSON.stringify({"username":"zhang", "password":"123"}),
                contentType:"application/json",
                dataType:"json",
                success:function(data){
                    alert(data.username);
                    alert(data.password);
                }
            });
        });
    });
</script>



@RequestMapping("/sayHello")
public @ResponseBody User sayHello(@RequestBody User user){
    System.out.println(user);
    return user;
}

3. SpringMVC实现文件上传

3.1 文件上传前置知识

  1. 文件上传的必要前提
    在这里插入图片描述
  2. 文件上传的原理分析
    在这里插入图片描述
    Content-Type: multipart/form-data; boundary=${bound}。其中${bound}是一个占位符,代表我们规定的分割符,可以自己任意规定,但为了避免和正常文本重复了,尽量要使用复杂一点的内容。如:--------------------56423498738365。如果不指定,会自动生成。

3.2 传统方式上传文件

  1. 导入文件上传的jar包
<!--上传文件用到的jar包-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
  1. 编写文件上传的JSP页面
<form action="hello/testUpload" method="post" enctype="multipart/form-data">
<label>点击按钮上传文件:</label>
    <input type="file" name="upLoad"> <br>
    <input type="submit" value="提交">
</form>
  1. 编写文件上传的Controller控制器
@RequestMapping("testUpload")
public String testUpload(HttpServletRequest request) throws Exception {
    //1. 得到要存放的目录
    String path = request.getSession().getServletContext().getRealPath("/upLoad/");
    //2. 判断目录是否存在,若不存在,则创建
    File file = new File(path);
    if (!file.exists()) {
        file.mkdir();
    }
    //3. 创建磁盘文件项工厂
    DiskFileItemFactory factory = new DiskFileItemFactory();
    ServletFileUpload upload = new ServletFileUpload(factory);
    //4. 解析request对象,得到请求项们
    List<FileItem> items = upload.parseRequest(request);
    //5. 遍历请求项,找到文件项
    for (FileItem item:items) {
        if (item.isFormField()){
            //是参数项
        } else {
            //是文件项
            String fileName = item.getName();
            //6. 使得文件名唯一
            String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase(); 
            fileName = uuid + "_" + fileName;
            //7. 将文件写入磁盘上
            item.write(new File(path, fileName));
            //8. 删除临时文件。默认小于10MB会生成缓存, 清除掉,避免开销
            item.delete();
        }
    }
    return "success";
}

3.3 springmvc方式上传文件

由于表现层的所有处理都交给前端控制器:dispatchaerServlet处理,所以,如果我们要利用框架解析request,获取文件项,再由dispatchaerServlet交给控制器处理,也是由dispatchaerServlet`处理。其工作流程如下:
在这里插入图片描述
注意:前端jsp上文件加项的name值必须与后台contriller中绑定方法的参数名一样,否则无法绑定参数。

  1. 配置文件解析器
<!-- 配置文件解析器对象,要求id名称必须是multipartResolver  CommonsMultipartResolver-通用组件解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <!--设置最大文件,字节为单位,10485760 = 10*1024*1024 = 10MB-->
     <property name="maxUploadSize" value="10485760"></property>
</bean>
  1. jsp页面不变。
  2. 编写文件上传的Controller控制器
    SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件,要求变量名称必须和表单file标签的 name属性名称相同。
@RequestMapping("testUpload")
public String testUpload(HttpServletRequest request, MultipartFile upLoad) throws Exception {
    //1. 得到要存放的目录
    String path = request.getSession().getServletContext().getRealPath("/upLoad/");
    //2. 判断目录是否存在,若不存在,则创建
    File file = new File(path);
    if (!file.exists()) {
        file.mkdir();
    }
    //3. 使得文件名唯一
    String fileName = upLoad.getOriginalFilename(); //注意:这里用getOriginalFilename()方法
    String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
    fileName = uuid + "_" + fileName;
    //4. 将文件写入磁盘上
    upLoad.transferTo(new File(path, fileName));
    return "success";
}

注意:上面获取文件名时,用的是getOriginalFilename()方法,而不是getName()方法。

3.4 SpringMVC跨服务器方式文件上传

  1. 搭建图片服务器
    重新建一个WEB项目,并运行,其webapp/upLoad/目录下,存放上传的文件。
  2. jsp页面不变。
  3. 编写文件上传的Controller控制器
@RequestMapping(value="/fileupload3")
public String fileupload3(MultipartFile upload) throws Exception{
	// 1. 定义图片服务器的请求路径        
	String path = "http://localhost:9090/day02_springmvc5_02image/upLoad/"; 
	// 2. 获取到上传文件的名称        
	String filename = upload.getOriginalFilename(); 
	// 3. 把文件的名称唯一化
	String uuid = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();                
	filename = uuid+"_"+filename; 

	// 4. 向图片服务器上传文件
	//4.1 创建客户端对象
	Client client = Client.create();
	// 连接图片服务器
	WebResource webResource = client.resource(path+filename);
	// 上传文件
	webResource.put(upload.getBytes());
	return "success";
}

4. SpringMVC的异常处理

4.1 异常处理思路

Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进 行异常的处理。 关系如下图:
在这里插入图片描述

4.2 SpringMVC的异常处理

在这里插入图片描述

  1. 自定义异常类,即自定义类继承
package cn.wanghao.springmvc.exception;

public class SysException extends Exception {
    private String message;

    public SysException(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
  1. 自定义异常处理器,继承HandlerExceptionResolver接口
package cn.wanghao.springmvc.exception;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SysExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        SysException err = null;
        if (e instanceof SysException) {
            err = (SysException) e;
        } else {
            err = new SysException("请联系管理员");
        }
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg", err);
        mv.setViewName("error");
        return mv;
    }
}

  1. 配置异常处理器
    除了dispatcaherServlet是在web.xml配置外。其余的什么器都是其类或者自定义其继承类,在springmvc.xml中用bean标签实例化就构成了什么什么器,
<!--开启异常处理器-->
<bean id="sysExceptionResolver" class="cn.wanghao.springmvc.exception.SysExceptionResolver"></bean>
  1. 出现异常的地方:
@RequestMapping("/myExcepion")
public String testMyExcepion() throws SysException {
    try {
        int i = 10/0;
    } catch (Exception e) {
        //打印错误信息
        e.printStackTrace();
        //抛出异常
        throw new SysException("查询用户出错!");
    }
    return "success";
}

5. SpringMVC中的拦截器

5.1 拦截器作用

在这里插入图片描述
简单来说,拦截器与过滤器功能类似,但是过滤器比拦截器的范围更大。

5.2 自定义拦截器

5.2.1 第一步:编写一个普通类实现 HandlerInterceptor 接口

HandlerInterceptor 接口的定义如下:
在这里插入图片描述
上述的代码中,preHandler()和postHandler()可以使用转发与重定向。

编写拦截器,可以用Ctrl + O查看已经继承的类以及类的方法:

package cn.wanghao.springmvc.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class InterceptorResolver implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("执行拦截器...去");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("执行拦截器...来");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("最后拦截器释放资源");
    }
}

5.2.2 第二步:配置拦截器

<!--开启拦截器-->
<mvc:interceptors>
    <!--配置第一个拦截器-->
    <mvc:interceptor>
        <!--要拦截哪些路径-->
        <mvc:mapping path="/hello/*"/>
        <!--不要拦截哪些路径-->
        <!--<mvc:exclude-mapping path="/hello/*" />-->
        <!--配置自己编写的拦截器-->
        <bean class="cn.wanghao.springmvc.interceptor.InterceptorResolver"></bean>
    </mvc:interceptor>
    <!--后续第二个...拦截器-->
</mvc:interceptors>

结果:
在这里插入图片描述
多个拦截器的时候:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ElegantCodingWH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值