springMVCDemo02响应数据和结果视图&实现文件上传&异常处理&拦截器

一:响应数据
1. 字符串:controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址
2.无返回值:可以通过resquest转向页面 和 response页面重定向和response指定响应结果
3.视图:modelAndView是SpringMVC为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
4.转发和重定向
5.异步请求

依旧先上结构图

在这里插入图片描述

1. 导入jar包
<artifactId>spring-context</artifactId>
<artifactId>spring-web</artifactId>
 <artifactId>spring-webmvc</artifactId>	
 <artifactId>servlet-api</artifactId>
 //下面三个是用作异步处理的
 <artifactId>jackson-databind</artifactId>
 <artifactId>jackson-core</artifactId>
 <artifactId>jackson-annotations</artifactId>
  1. 实体类 user
	private String username;
    private String password;
    private Integer money;
  1. 控制器
@Controller
@RequestMapping("demo01")
public class demo01response {
    
    
    @RequestMapping("/testVoid")
    public String testVoid(Model model){
    
    
        user user = new user();
        user.setUsername("张三");
        user.setPassword("123");
        user.setMoney(100);
        model.addAttribute("user",user);
        return "success";
    }
    @RequestMapping("/testReturnVoid")
    public void testReturnVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("测试无返回值");
        //1、使用 request 转向页面
        //request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response);
        //2、也可以通过 response 指定响应结果
        response.sendRedirect("testVoid");
        //3、也可以通过 response 指定响应结果
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("json 串");
        return ;
    }
    @RequestMapping("/testReturnModelAndView")
    public ModelAndView testReturnModelAndView()  {
    
    
        //ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("one","张三");
        /*我们在页面上上获取使用的是 requestScope.one取的,所以返回 ModelAndView 类型时,浏
        览器跳转只能是请求转发。*/
        modelAndView.setViewName("success");
        return modelAndView;
    }

    @RequestMapping("/testForward")
    public String testForward()  {
    
    
        System.out.println("测试转发");;
        /*需要注意的是,如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图。
        它相当于“request.getRequestDispatcher("url").forward(request,response)”。使用请求
        转发,既可以转发到 jsp,也可以转发到其他的控制器方法。
        */
        return "forward:/WEB-INF/pages/success.jsp";
    }
    @RequestMapping("/testRedirect")
    public String testRedirect()  {
    
    
        System.out.println("测试转发");
        /*它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不
    能写在 WEB-INF 目录中,否则无法找到。*/
        return "redirect:testReturnModelAndView";
    }

    /**
     * 获取请求体的数据,异步请求
     */
    @RequestMapping("/testJson")
    public  @ResponseBody user testJson(@RequestBody user user){
    
    
        System.out.println(user);
        user.setUsername("bb");
        return user;
    }
}
  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">
            <!-- 配置创建 spring 容器要扫描的包 -->
    <context:component-scan base-package="lml.demo01"></context:component-scan>

    <!-- 配置视图解析器 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--文件所在的目录-->
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <!--文件的后缀名-->
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!-- 设置静态资源不过滤 -->
    <mvc:resources location="/css/" mapping="/css/**"/> <!-- 样式 -->
    <mvc:resources location="/images/" mapping="/images/**"/> <!-- 图片 -->
    <mvc:resources location="/js/" mapping="/js/**"/> <!-- javascript -->

    <!--开启注解springMVC的支持-->
    <mvc:annotation-driven />
</beans>
  1. 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">
  <display-name>Archetype Created Web Application</display-name>


  <servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--配置初始化参数,用于读取springmvc的配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springMVC.xml</param-value>
    </init-param>
    <!--配置servlet 的对象的创建时间点,应用加载时创建,取值只能时非0正整数,表示启动顺序-->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!--所有的都要拦截-->
  <servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--解决乱码问题-->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!-- 设置过滤器中的属性值 -->
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <!-- 启动过滤器 -->
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

  1. 前端
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>lml</title>
    <script src="js/jquery.min.js"></script>
    <script>
        $(function(){
    
    
            //绑定点击事件
            $("#bt1").click(function () {
    
    
                $.ajax({
    
    
                    url:"demo01/testJson",
                    contentType:"application/json;charset=UTF-8",
                    data:'{"username":"aa","password":"123","money":"100"}',
                    type:"post",
                    success:function (data) {
    
    
                            alert(data);
                            alert(data.username)
                    }
                })
            })
        }
        )
    </script>
</head>
<body>
<a href="demo01/testVoid">测试</a>
<a href="demo01/testReturnVoid">测试无返回值</a>
<br/>
<a href="demo01/testReturnModelAndView">测试模型视图</a>
<br/>
<a href="demo01/testForward">测试转发</a>
<a href="demo01/testRedirect">测试重定向</a>
<br/>
<button id="bt1">测试响应json,发送json请求</button>
</body>
</html>
  1. 此外 需要导入
jquery.min.js  文件
  1. 跳转成功的页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
        <h4>成功了</h4>
    ${
    
    user}
    ${
    
    user.username}
    ${
    
    user.password}
        <br/>
    测试modelAndView ${
    
    requestScope.one}
</body>
</html>

二:文件上传
1. 文件上传的必要前提
a. form表单的enctype(是表单请求正文的类型)取值必须是multipart/form-data。
b. method属性值必须是Post
2.文件上传原理的分析
当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。
enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:
key=value&key=value&key=value
当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成:
每一部分都是 MIME 类型描述的正文
3.代码实现
依旧上结构图
在这里插入图片描述
跟上面的项目相比
不变的是:跳转成功的jsp页面、实体类user,web.xml
变的是:
控制器:

@Controller
@RequestMapping("demo01")
public class demo01response {
    
    
    /**
     * 传统文件上传的方式
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/fileLoad1")
    public String fileLoad1(HttpServletRequest request) throws Exception {
    
    
        //先获取到要上传得文件目录
        String path = request.getSession().getServletContext().getRealPath("/upLoad");
        //创建file对象,一会向该路径下上传文件
        File file = new File(path);
        System.out.println(path);
        //判断路径是否存在,如果不存在,创建该路径
        if (!file.exists()){
    
    
            file.mkdirs();
        }
        //创建磁盘文件项工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        //解析request对象
        List<FileItem> list = fileUpload.parseRequest(request);
        //遍历
        for (FileItem fileItem : list) {
    
    
            //判断文件项,还是上传得文件
            if (fileItem.isFormField()){
    
    

            }else {
    
    
                //获取到上传文件得名称
                String name = fileItem.getName();
                //上传文件
                fileItem.write(new File(file,name));

                //删除临时文件
                fileItem.delete();
            }
        }
        return "success";
    }

    /**
     * springMVC传统方式文件上传
     * @param request
     * @param upload
     * @return
     * @throws Exception
     */
    @RequestMapping("/fileLoad2")
    public String fileLoad2(HttpServletRequest request, MultipartFile upload) throws Exception {
    
    
        //先获取到要上传得文件目录
        String path = request.getSession().getServletContext().getRealPath("/upLoad");
        //创建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";
    }
}
springMVC.xml
添加了配置文件解析器对象,要求id名称必须是multipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760"></property>
    </bean>

前端页面

<%--
  Created by IntelliJ IDEA.
  User: ASUS
  Date: 2021/5/3
  Time: 18:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
        <form action="demo01/fileLoad1" method="post" enctype="multipart/form-data">
            选择文件 <input type="file" name="upload"><br/>
            <input type="submit" value="提交">
        </form>


        <form action="demo01/fileLoad2" method="post" enctype="multipart/form-data">
            选择文件 <input type="file" name="upload"><br/>
            <input type="submit" value="提交">
        </form>
</body>
</html>

pom文件 因为需要文件流
<artifactId>commons-io</artifactId>
 <artifactId>commons-fileupload</artifactId>

ps:还有跨服务器实现文件上传

应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
缓存和消息服务器:负责处理大并发访问的缓存和消息
文件服务器:负责存储用户上传文件的服务器。

三:异常处理
1. 流程
客户端请求->springmvc DispatcherServlet-controller-Service-dao异常抛出
-Service-controller-springmvc DispatcherServlet-HandlerExceptionResolver(异常处理器)

	Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进

行异常的处理。
2. 代码实现
在这里插入图片描述

2.0  pom.xml  web.xml 文件与第一份的一样
2.1 前端页面
 <a href="demo01/testException" >异常处理</a>
	2.2 控制器
@Controller
@RequestMapping("demo01")
public class contro {
    
    
    @RequestMapping("/testException")
    public String testException() throws SysException {
    
    
        System.out.println("testException执行了...");

        try {
    
    
            // 模拟异常
            int a = 11/0;
        } catch (Exception e) {
    
    
            // 打印异常信息
            e.printStackTrace();
            // 抛出自定义异常信息
            throw new SysException("查询所有用户出现错误了...");
        }
        return "success";
    }
}
public class SysException extends Exception {
    
    
    private String message;

    public String getMessage() {
    
    
        return message;
    }

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public SysException(String message) {
    
    
        this.message = message;
    }
}
public class SysExceptionResolver implements HandlerExceptionResolver {
    
    
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
    
    
        //获取到异常对象
        SysException s=null;
        if (e instanceof SysException){
    
    
                    s = (SysException)  e;
        }else {
    
    
            e=new SysException("系统正在维护");
        }
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg",e.getMessage());
        mv.setViewName("error");
        return mv;
    }
}

2.3 springMVC.xml
<!-- 配置创建 spring 容器要扫描的包 -->
    <context:component-scan base-package="lml"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--文件所在的目录-->
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <!--文件的后缀名-->
        <property name="suffix" value=".jsp"></property>
    </bean>

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

    <mvc:annotation-driven />
    <!--开启注解springMVC的支持-->
2.4 错误页面
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${
    
    errorMsg}
</body>
</html>

四:拦截器
1. 基础知识:SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
2.拦截器和过滤器的区别
2.1 过滤器是servlet规范中的一部分,任何java web都可以使用
过滤器在url-pattern中配置了/*之后,可以对所有要访问的资源拦截
2.2 拦截器是springMVC框架,只有使用了springMVC框架才可以使用
拦截器只会拦截访问的控制器方法,如果访问的是jsp,html,js…是不会拦截的。
想要自定义拦截器,需要实现HandlerInterceptor接口。
3. 代码简单的实现
在这里插入图片描述

3.0  pom.xml  、web.xml 、success、error一样
3.1 前端
<a href="demo01/testInterceptor" >异常处理</a>
3.2 控制器
@Controller
@RequestMapping("/demo01")
public class demo01 {
    
    
    @RequestMapping("/testInterceptor")
    public String testInterceptor(){
    
    
        System.out.println("运行成功");
        return "success";
    }
}
public class HandlerInterceptorDemo1 implements HandlerInterceptor {
    
    
    /**
     * 预处理,controller方法执行前
     * return true 放行,执行下一个拦截器,如果没有,执行controller中的方法
     * return false不放行
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        System.out.println("MyInterceptor1执行了...前1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
        return true;
    }

    /**
     * 后处理方法,controller方法执行后,success.jsp执行之前
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
    
        System.out.println("MyInterceptor1执行了...后1111");
        // request.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(request,response);
    }

    /**
     * success.jsp页面执行后,该方法会执行
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
    
        System.out.println("MyInterceptor1执行了...最后1111");
    }
}
3.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">
    <!-- 配置创建 spring 容器要扫描的包 -->
    <context:component-scan base-package="lml"></context:component-scan>
    <!-- 配置视图解析器 -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--文件所在的目录-->
        <property name="prefix" value="/WEB-INF/pages/"></property>
        <!--文件的后缀名-->
        <property name="suffix" value=".jsp"></property>
    </bean>
    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/demo01/*"/><!-- 用于指定对拦截的 url -->
        <bean  class="lml.interceptoe.HandlerInterceptorDemo1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    <!--开启注解springMVC的支持-->
    <mvc:annotation-driven />

</beans>

注:

  1. preHandle方法是controller方法执行前拦截的方法
  2. 可以使用request或者response跳转到指定的页面
  3. return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
  4. return false不放行,不会执行controller中的方法。
  5. postHandle是controller方法执行后执行的方法,在JSP视图执行前。
  6. 可以使用request或者response跳转到指定的页面
  7. 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
  8. postHandle方法是在JSP执行后执行
  9. request或者response不能再跳转页面了

对了 创建maven文件时
添加 archetypeCatalog - internal

猜你喜欢

转载自blog.csdn.net/weixin_46809332/article/details/116433839