SSM框架之SpringMVC进阶(二)

一、响应数据和结果视图

1. 返回值分类之:字符串

controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。

2. 返回值分类之:void

Servlet原始Api可作为控制器中方法的参数,在Controller方法形参上定义request和response,使用request和response指定响应结果。

3. 返回值分类之:ModelAndView对象

ModelAndView是spring提供的一个对象,可以用来调整具体的JSP视图。

二、响应之转发和重定向

  • forward转发:
    Controller方法在提供了String类型的返回值之后,默认就是请求转发。
    需要注意的是:如果用了formward,则路径必须写成实际视图url,不能写逻辑视图。
    //相当于
    request.getRequestDispatcher("url").forward(request,response)
    
    使用请求转发,既可以转发到jsp,也可以转发到其他的控制器方法。
  • redirect重定向


三、ResponseBody响应json数据

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

     <!--前端控制器,配置那些资源不用拦截    -->
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/images/**" location="/images/"/>
    <mvc:resources mapping="/css/**" location="/css/"/>
  • 使用@ResponseBody注解实现将controller方法返回对象转换为json响应给客户端。


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

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

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

二、SpringMVC实现文件上传

1. 文件上传的必要前提

  • form表单的enctype取值必须是:multipart/form-data(默认值是:application/x-www-from-urlencoded)
    enctype:是表单请求正文的类型。
  • method属性取值必须是post
  • 提供一个文件选择域
    <input  type = "file" />
    

2.文件上传的原理属性:

  • 当form表单的enctype取值不是默认后,request.getParameter()将失效。enctype="application/x-www-form-urlencoded"时,form表单的正文内容是:key=value&key=value&key=value
  • 当form表单的enctype取值为Mutilpart/form-data时,请求正文内容就会变成:
    每一部分都是MIME类型描述的正文。
  • 借助第三方组件实现文件上传:
    使用Commons-fileUpload组件实现文件上传,需要导入该组件相应的jar包:Commons-fileupload和Commons-io。commons-io不属于文件上传组件开发的jar文件,但Commons-fileUpload组件从1.1版本开始,它工作时需要commons-io包的支持。


3. jsp文件上传表单的实现

 <h3>文件上传</h3>

    <form action="file/upload" method="post" enctype="multipart/form-data">
        选择上传文件:<input type="file" name="upload"/><br/>
        <input type="submit" value="上传"/>

    </form>

4. SpringMVC中文件解析器的配置

<!--配置文件解析器
       文件上传的id是固定的,不能起别的名称,否则无法实现请求参数的绑定。
       -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760"/>
    </bean>

5. 文件上传代码实现

package com.seapp.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.RequestPartServletServerHttpRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * @author seapp
 * @date 2020/8/3 23:14
 */
@Controller
@RequestMapping("/file")
public class FileUploadController {

    /**
     * 实现文件上传
     *
     * @return
     */
    @RequestMapping("/upload")
    public String fileUpload(HttpServletRequest request, MultipartFile upload) throws IOException {
        System.out.println("SpringMVC文件上传开始");

        //获取文件上传路径
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        //判断该文件是否存在,不存在则创建该文件
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }

        //获取上传文件信息
        String filename = upload.getOriginalFilename();
        //把文件的名称设置唯一值,uuid
        filename = UUID.randomUUID().toString().replace("-", "") + "_" + filename;
        //完成文件上传
        upload.transferTo(new File(path,filename));
        return "success";
    }
}

6.SpirngMVC跨服务器方式实现文件上传

  • 三方访问依赖的引入:
  <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>
  • 文件跨服务传输的具体实现:

    /**
     * 实现文件上传
     *
     * @return
     */
    @RequestMapping("/upload")
    public String fileUpload(HttpServletRequest request, MultipartFile upload) throws IOException {
        System.out.println("SpringMVC文件上传开始");

        String path = "http://localhost:8090/uplods/";
        //获取上传文件信息
        String filename = upload.getOriginalFilename();
        //把文件的名称设置唯一值,uuid
        filename = UUID.randomUUID().toString().replace("-", "") + "_" + filename;

        //创建客户端对象
        Client client = Client.create();
        WebResource webResource = client.resource(path + filename);
        //完成文件上传
        webResource.put(upload.getBytes());

        return "success";
    }

三、SpringMVC中的异常处理

1. 自定义异常类(做提示信息的)

package com.seapp.exception;

/**

  • 自定义异常处理类
  • @author seapp
  • @date 2020/8/4 15:53
    */
    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;
}

}

2. 编写异常处理器

package com.seapp.exception;

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

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

/**
 * 异常处理器
 * @author seapp
 * @date 2020/8/4 15:57
 */
public class SysExceptionResolver implements HandlerExceptionResolver {
    /**
     * 异常处理逻辑
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @return
     */
    @Override
    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 = new ModelAndView();
        modelAndView.addObject("errorMsg",e.getMessage());
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

3. 配置异常处理器(跳转到友好处理界面 )


    <!--配置异常处理器    -->
    <bean id="sysExceptionResolver" class="com.seapp.exception.SysExceptionResolver"/>

四、SpringMVC中的拦截器

1. 拦截器

  • Spring MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
  • 用户可以自己定义一些拦截器来实现特定功能。
  • 谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
  • 过滤器与拦截器的区别:
    ①:过滤器是Servlet规范中的一部分,任何Java web工程都可以使用。
    ②:拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能用。
    ③:过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截。
    ④:拦截器它是只会拦截访问的控制器方法,如果访问的是jsp、html、css、image或者js是不会进行拦截的。
  • 它也是AOP思想的具体应用。
  • 我们要想自定义拦截器,要求必须实现"HandlerInterceptor"接口。

2.拦截器实现

  • 编写拦截器,实现HandlerInterceptor接口
package com.seapp.interceptor;

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

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

/**
 * 自定义拦截器
 * @author seapp
 * @date 2020/8/4 16:47
 */
public class MyInterceptor  implements HandlerInterceptor {

    /**
     * 拦截器预处理
     * @param request
     * @param response
     * @param handler
     * @return
     *      true:放行,若拦截链中还有拦截器,则执行下个拦截器。若没有,则执行Controller中的方法
     *      false:拦截。使用request/response参数,直接跳转至指定界面。
     *
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        return true;
    }

    /**
     * 后处理的方法
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {

    }

    /**
     * 最后执行的方法
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {

    }
}

  • 配置拦截器(springmvc.xml)
 <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--要拦截的方法-->
            <mvc:mapping path="/user/**"/>
            <!--不要拦截的方法-->
<!--        <mvc:exclude-mapping path="/**"/>-->
            <!--配置拦截器对象-->
            <bean class="com.seapp.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352