当前位置: 首页>数据库>正文

spring 下载返回文件流 springmvc返回文件

SpringMVC学习之路 第二篇

  • 在第一篇的基础上,今天我们继续学习SpringMVC框架。
  • 本文涉及以下内容:
1. 响应数据返回值 。
2. ResponseBody 响应 json 数据 。
3. SpringMVC实现文件上传 。
4. SpringMVC异常处理 。
5. SpringMVC拦截器 。

1. 响应数据返回值

  • 响应数据的返回值有String类型、void类型和ModelAndView。
1.1 返回值类型是String类型:
  • 顺便复习下Attribute
  1. 编写response.jsp文件:
<a href="user/testString">testString</a>
  1. 编写User类(domain/User.java),忽略get等方法:
public class User implements Serializable {
    private String username;
    private String password;
    private Integer age;
  1. 编写UserController类(controller/UserController.java):
@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/testString")
    public String testString(Model model) {
        System.out.println("testString方法执行了");
        //模拟从数据库拿User对象
        User user = new User();
        user.setUsername("美美");
        user.setPassword("123");
        user.setAge(25);
        //model对象
        model.addAttribute("user", user);
        return "success";
    }
}
  1. 编写成功跳转页面success.jsp(WEB-INF/pages/success.jsp):
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <h3>执行成功。。。</h3>
        ${user.username}
        ${user.password}
        ${user.age}
    </body>
</html>
1.2 返回值类型是void类型:
  • 转发和重定向的区别如下:
  • request.getRequestDispatcher().forward(request,response):
  1. 属于转发,也是服务器跳转,相当于方法调用,在执行当前文件的过程中转向执行目标文件,两个文件(当前文件和目标文件)属于同一次请求,前后页共用一个request,可以通过此来传递一些数据或者session信息,request.setAttribute()和request.getAttribute()。
  2. 在前后两次执行后,地址栏不变,仍是当前文件的地址。
  3. 不能转向到本web应用之外的页面和网站,所以转向的速度要快。
  4. URL中所包含的“/”表示应用程序(项目)的路径。
  • response.sendRedirect():
  1. 属于重定向,也是客户端跳转,相当于客户端向服务端发送请求之后,服务器返回一个响应,客户端接收到响应之后又向服务端发送一次请求,一共是2次请求,前后页不共用一个request,不能读取转向前通过request.setAttribute()设置的属性值。
  2. 在前后两次执行后,地址栏发生改变,是目标文件的地址。
  3. 可以转向到本web应用之外的页面和网站,所以转向的速度相对要慢。
  4. URL种所包含的"/"表示根目录的路径。
  • 增加response.jsp的内容:
<a href="user/testVoid">testVoid</a>
  1. 若不写返回值,也没有转发和重定向,它会默认跳转到WEB-INF/pages/user/testVoid.jsp。我们可以在它默认的位置编写相应的jsp文件就可以啦。看UserCOntroller代码:
@Controller
@RequestMapping("/user")
public class UserController {
estMapping("/testVoid")
    public void testVoid() {
        System.out.println("testVoid方法执行了");
    }
}
  1. 采用请求转发模式,编写UserController:
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
    System.out.println("testVoid方法执行了");
    //编写请求转发的程序
    request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
}
  1. 采用response页面重定向,编写UserController:
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
    System.out.println("testVoid方法执行了");
    //重定向
    response.sendRedirect(request.getContextPath()+"/index.jsp");
  1. 直接进行响应的方式:
@RequestMapping("/testVoid")
public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
    System.out.println("testVoid方法执行了");
    //直接会进行响应
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=UTF-8");
    response.getWriter().println("你好,世界");
}

1.3 返回值类型是ModeAndView类型:
  • 前面返回值String类型(和Model)底层就是用这种方式实现的。
  1. 编写response.jsp:
<a href="user/testModelAndView">testModelAndView</a>
  1. 编写UserController类:
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
    //创建ModelAndView对象
    ModelAndView mv = new ModelAndView();
    System.out.println("testModelAndView方法执行了");
    //模拟从数据库拿User对象
    User user = new User();
    user.setUsername("美美");
    user.setPassword("123");
    user.setAge(25);
    //把user对象存储在mv对象中,也把user对象存入到request对象
    mv.addObject("user", user);
    mv.setViewName("success");
    return mv;
}
1.4 用关键字做转发和重定向:
  1. 编写response.jsp:
<a href="user/testForwardOrRedirect">testModelAndView</a>
  1. 编写UserController类:
@RequestMapping("/testForwardOrRedirect")
public String testForwardOrRedirect() {
    System.out.println("testString方法执行了");
    //请求的转发
    //return "forward:/WEB-INF/pages/success.jsp";
    //重定向
    return "redirect:/index.jsp";
}

2. ResponseBody 响应 json 数据

2.1 过滤静态资源,哪些静态资源不被拦截
  1. 添加css,images,js等目录
  • webapp/css webapp/images webapp/js
  1. 在springmvc.xml中配置:
<!--前端控制器,哪些静态资源不拦截-->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/>
<mvc:resources location="/js/" mapping="/js/**" />
2.2 发送ajax请求
  1. 导入jquery包。
    将jquery.min.js包导入到webapp/js中
  2. 编写response.jsp(webapp/response.jsp):
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
        <script src="js/jquery.min.js"></script>
        <script>
            //页面加载,绑定单击时间
            $(function () {
               $("#btn").click(function () {
                   $.ajax({
                       url: "user/testAjax",
                       contentType: "application/json;charset=UTF-8",
                       data: '{"username":"hehe","password":"123","age":30}',
                       dataType: "json",
                       type: "post",
                       success: function (data) {
                           //data服务器端响应的json数据,进行解析
                            alert(data);
                            alert(data.username);
                            alert(data.password);
                            alert(data.age);
                       }
                   });
               });
            });
        </script>
    </head>
    <body>
        <button id="btn">发送ajax</button>
    </body>
</html>
  1. 添加jackson包,让springmvc支持json数据格式的解析和和转换,在pom.xml添加如下:
<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>
  1. 添加UserController中内容:
  • 返回值User前面也要用ResponseBody注解,表示返回的是json类型的。
//模拟异步请求响应
@RequestMapping("/testAjax")
public @ResponseBody User testAjax(@RequestBody User user) {
    System.out.println("testAjax方法执行了");
    System.out.println(user);
    user.setUsername("haha");
    user.setAge(40);
    return user;
}

3. SpringMVC实现文件上传

3.1 文件上传之传统方式上传
  1. 编写index.jsp文件:
  • form 表单的 enctype 取值必须是:multipart/form-data,(默认值是:application/x-www-form-urlencoded)。
  • enctype:是表单请求正文的类型
  • multipart/form-data:指定传输数据为二进制数据,例如图片、mp3、文件
  • application/x-www-from-urlencoded:只能上传键值对,并且键值对都是间隔分开的。
<h3>传统文件上传</h3>
<form action="/user/fileupload1" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"> <br>
    <input type="submit" value="上传">
</form>
  1. 在pom.xml中导入上传文件需要的包:
  • commons-fileupload依赖于commons-i包
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>
  1. 编写UserController:
@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/fileupload1")
    public String fileupload1(HttpServletRequest request) throws Exception {
        System.out.println("文件上传。。。");
        //使用fileupload组件完成文件上传
        //路径
        String path = request.getSession().getServletContext().getRealPath("/uploads/");
        //判断路径是否存在
        File file = new File(path);
        if(!file.exists()) {
            file.mkdirs();
        }
        //解析request对象,获取上传文件项
        DiskFileItemFactory factory = new DiskFileItemFactory();// 磁盘文件对象
        ServletFileUpload upload = new ServletFileUpload(factory);// 文件上传对象
        List<FileItem> items = upload.parseRequest(request); // 将表单中的所有数据信息放入 list容器中
        for(FileItem item: items) {
            //进行判断,当前item对象是否是上传文件项
            if(item.isFormField()) {
                //说明普通表单项
            } else { //上传文件项
                String filename = item.getName(); //获取名称
                //用uuid更改为唯一的名称
                String uuid = UUID.randomUUID().toString().replace("-", "");
                filename = uuid + "_" + filename;
                item.write(new File(path, filename)); //完成文件上传
                item.delete(); //删除临时文件
            }
        }
        return "success";
    }
}

3.2 文件上传之SpringMVC方式
  1. pom.xml中的commons-fileupload和commons-io包不能少
  2. 编写index.jsp:
<h3>SpringMVC文件上传</h3>
<form action="/user/fileupload2" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"> <br>
    <input type="submit" value="上传">
</form>
  1. 在springmvc.xml中添加文件的解析器:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解扫描 -->
    <context:component-scan base-package="fang"/>

    <!-- 视图解析器对象 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--前端控制器,哪些静态资源不拦截-->
    <mvc:resources location="/css/" mapping="/css/**"/>
    <mvc:resources location="/images/" mapping="/images/**"/>
    <mvc:resources location="/js/" mapping="/js/**"/>

    <!--配置文件解析器对象-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760" /> <!--10M-->
    </bean>

    <!-- 开启SpringMVC框架注解的支持 -->
    <mvc:annotation-driven />
</beans>
  1. 编写UserController:
  • MultipartFile upload中的upload和< input type=“file” name=“upload” >中的name属性保持一致
@RequestMapping("/fileupload2")
public String fileupload2(HttpServletRequest request, MultipartFile upload) throws Exception {
    System.out.println("SpringMVC文件上传。。。");
    //使用fileupload组件完成文件上传
    //路径
    String path = request.getSession().getServletContext().getRealPath("/uploads/");
    //判断路径是否存在
    File file = new File(path);
    if(!file.exists()) {
        file.mkdirs();
    }
    String filename = upload.getOriginalFilename();
    //用uuid更改为唯一的名称
    String uuid = UUID.randomUUID().toString().replace("-", "");
    filename = uuid + "_" + filename;
    upload.transferTo(new File(path, filename));
    return "success";
}

4. SpringMVC异常处理

4.1 编写index.jsp:

<h3>异常处理</h3>
<a href="user/testException">异常处理</a>

4.2 编写异常类(exception/SysException),省略get和set方法:

public class SysException extends Exception {
    private String message;

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

4.3 编写异常处理类(exception/SysExceptionResolver):

public class SysExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        SysException ex = null;
        if(e instanceof SysException) {
            ex = (SysException) e;
        } else {
            ex = new SysException("系统正在维护。。。");
        }
        //创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg", e.getMessage());//存入值
        mv.setViewName("error");//跳转到error.jsp页面
        return mv;
    }
}

4.4 在springmvc.xml中添加异常处理器:

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

4.5 编写error.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${errorMsg}
</body>
</html>

4.6 编写UserController:

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/testException")
    public String testException() throws SysException {
        System.out.println("testException执行了。。。");
        try {
            int a = 10 / 0;
        } catch (Exception e) {
            e.printStackTrace();
            //抛出自定义异常信息
            throw new SysException("查询用户出错");
        }
        return "success";
    }
}

5. SpringMVC拦截器

  • 过滤器是 servlet 规范中的一部分,任何 java web 工程都可以使用。
  • 拦截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程
  • 才能用。
  • 过滤器在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
  • 拦截器它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。
  • 我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。

5.1 编写index.jsp:

<h3>拦截器</h3>
<a href="user/testInterceptor">拦截器</a>

5.2 编写拦截器类(interceptor/MyInterceptor):

  • preHandle:方法执行之前拦截
  • postHandle:方法执行之后,跳转页面执行之前拦截
  • afterCompletion:跳转页面执行之后拦截
  • preHandle方法返回值为false表示不放行,true为放行。
public class MyInterceptor1 implements HandlerInterceptor {

    @Override //预处理,controller方法执行前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1执行了");
//        request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request, response);
        return true;//true放行,false不放行
    }

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

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1执行了...最后");
    }
}

5.3 编写成功跳转页面success.jsp:

  • <% System.out.println(“success.jsp执行了。。。”); %>为java代码,会在控制台输出。
<h3>执行成功。。。</h3>
<% System.out.println("success.jsp执行了。。。"); %>

5.4 编写UserController类:

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/testInterceptor")
    public String testInterceptor() {
        System.out.println("testInterceptor执行了");
        return "success";
    }
}

5.5 在springmvc.xml中配置拦截器:

  • path="/user/* 为拦截范围路径为/user下的所有目录,比如/user/testInterceptor
<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/user/*"/> <!--要拦截的具体的方法-->
        <!--<mvc:exclude-mapping path=""/>--> <!--不要拦截的方法-->
        <!--配置拦截器对象-->
        <bean class="fang.interceptor.MyInterceptor1"/>
    </mvc:interceptor>
</mvc:interceptors>



https://www.xamrdz.com/database/6br1937726.html

相关文章: