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>
  2. 编写User类(domain/User.java),忽略get等方法:
    public class User implements Serializable {
        private String username;
        private String password;
        private Integer age;
  3. 编写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";
        }
    }
  4. 编写成功跳转页面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方法执行了");
        }
    }
  2. 采用请求转发模式,编写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);
    }
  3. 采用response页面重定向,编写UserController:
    @RequestMapping("/testVoid")
    public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("testVoid方法执行了");
        //重定向
        response.sendRedirect(request.getContextPath()+"/index.jsp");
  4. 直接进行响应的方式:
    @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>
  2. 编写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>
  2. 编写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
  2. 在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>
  3. 添加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>
  4. 添加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>
  3. 在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>
  4. 编写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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值