zoukankan      html  css  js  c++  java
  • SpringMVC:第二篇

    第一章:响应数据和结果视图

    1.1-返回值分类

    1.1.1-字符串

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

    //指定逻辑视图名,经过视图解析器解析为 jsp 物理路径:/WEB-INF/pages/success.jsp
    @RequestMapping("/testReturnString")
    public String testReturnString() {
        System.out.println("AccountController 的 testReturnString 方法执行了。。。。");
        return "success";
    }
    
    

    1.1.2-void

    我们知道 Servlet 原始 API 可以作为控制器中方法的参数:

    @RequestMapping("/testReturnVoid")
    public void testReturnVoid(HttpServletRequest request,HttpServletResponse response)
    throws Exception {
    }
    

    在 controller 方法形参上可以定义 request 和 response,使用 request 或 response 指定响应结果 。

    1、使用 request 转向页面,如下

    request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,
    response);
    

    2、也可以通过 response 页面重定向

    response.sendRedirect("testRetrunString")
    

    3、也可以通过 response 指定响应结果,例如响应 json 数据

    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=utf-8");
    response.getWriter().write("json 串");
    

    1.1.3-ModelAndView

    ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值。

    该对象中有两个方法:

    示例代码:

    /**
    * 返回 ModeAndView
    * @return
    */
    @RequestMapping("/testReturnModelAndView")
    public ModelAndView testReturnModelAndView() {
        ModelAndView mv = new ModelAndView();
        mv.addObject("username", "张三");
        mv.setViewName("success");
        return mv;
    }
    

    响应的jsp代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>执行成功</title>
    </head>
    <body>
        执行成功!
        ${requestScope.username}
    </body>
    </html>
    

    执行结果:

    注意: 我们在页面上上获取使用的是 requestScope.username 取的,所以返回 ModelAndView 类型时,浏 览器跳转只能是请求转发。

    1.2-转发和重定向

    1.2.1-forward 转发

    controller 方法在提供了 String 类型的返回值之后,默认就是请求转发。我们也可以写成:

    /**
    * 转发
    * @return
    */
    @RequestMapping("/testForward")
    public String testForward() {
        System.out.println("AccountController 的 testForward 方法执行了。。。。");
        return "forward:/WEB-INF/pages/success.jsp";
    }
    

    需要注意的是,如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图 。

    它相当于“request.getRequestDispatcher("url").forward(request,response)”。使用请求 转发,既可以转发到 jsp,也可以转发到其他的控制器方法。

    1.2.2-Redirect 重定向

    contrller 方法提供了一个 String 类型返回值之后,它需要在返回值里使用:redirect:

    /**
    * 重定向
    * @return
    */
    @RequestMapping("/testRedirect")
    public String testRedirect() {
        System.out.println("AccountController 的 testRedirect 方法执行了。。。。");
        return "redirect:testReturnModelAndView";
    }
    
    

    它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不 能写在 WEB-INF 目录中,否则无法找到。

    1.3-@ResponseBody响应json数据

    1.3.1 使用说明

    作用: 该注解用于将 Controller 的方法返回的对象,通过 HttpMessageConverter 接口转换为指定格式的 数据如:json,xml 等,通过 Response 响应给客户端 。

    1.3.2-使用示例

    需求: 使用@ResponseBody 注解实现将 controller 方法返回对象转换为 json 响应给客户端。

    前置知识点: Springmvc 默认用 MappingJacksonHttpMessageConverter 对 json 数据进行转换,需要加入 jackson 的包。 Maven引入依赖包

        <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>
    

    jsp中的代码

    <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script>
    <script type="text/javascript">
    $(function(){
        $("#testJson").click(function(){
            $.ajax({
                    type:"post",
                    url:"${pageContext.request.contextPath}/testResponseJson",
                    contentType:"application/json;charset=utf-8",
                    data:'{"id":1,"name":"test","money":999.0}',
                    dataType:"json",
                    success:function(data){
                    alert(data);
                }
            });
        });
    })
    </script>
    <!-- 测试异步请求 -->
    <input type="button" value="测试 ajax 请求 json 和响应 json" id="testJson"/>
    

    控制器中的代码

    @Controller("jsonController")
    public class JsonController {
        /**
        * 测试响应 json 数据
        */
        @RequestMapping("/testResponseJson")
        public @ResponseBody Account testResponseJson(@RequestBody Account account) {
            System.out.println("异步请求:"+account);
            return account;
        }
    }
    
    

    运行结果:

    1.4-设置静态资源不被过滤

    1.4.1-方式1:

    在springmvc配置文件中设置

        <!-- 设置静态资源不过滤 -->
        <mvc:resources location="/css/" mapping="/css/**"/> 
        <mvc:resources location="/images/" mapping="/images/**"/> 
        <mvc:resources location="/js/" mapping="/js/**"/>
    

    1.4.2-方式2:

    在springmvc配置文件中设置

    <mvc:default-servlet-handler/>
    

    第二章:SpringMVC 实现文件上传

    2.1-springmvc传统方式的文件上传

    2.1.1-说明

    传统方式的文件上传,指的是我们上传的文件和访问的应用存在于同一台服务器上。

    并且上传完成之后,浏览器可能跳转。

    2.1.2-实现步骤

    第一步:Maven引入文件上传的 jar 包到工程

    <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.4</version>
    </dependency>
    

    第二步:编写 jsp 页面

    <form action="file/upload01" method="post" enctype="multipart/form-data">
        <input type="file" name="upload" >
        <input type="submit" value="上传图片">
    </form>
    

    第三步:编写控制器

    @RequestMapping("file")
    public class UploadController {
      @RequestMapping("upload01")
      public String fileUpload01(HttpServletRequest request, MultipartFile upload) throws IOException {
        System.out.println("SpringMVC传统方式上传图片");
        // 先获取到要上传的文件目录
        String path = request.getSession().getServletContext().getRealPath("/uploads");
        System.out.println(path);
        // 创建File对象,一会向该路径下上传文件
        File file = new File(path);
        // 判断路径是否存在,如果不存在,创建该路径
        if(!file.exists()){
          file.mkdirs();
        }
        // 获取到上传文件的名称
        String filename = upload.getOriginalFilename();
        // 文件名唯一
        filename = UUID.randomUUID().toString().replaceAll("-","") +"."+ filename.split("\.")[1];
        // 上传文件
        upload.transferTo(new File(file,filename));
        System.out.println("上传成功");
        return "success";
      }
    }
    

    第四步:配置文件解析器

    在springMvc配置文件中配置

    <!-- 配置文件上传解析器 -->
    <bean id="multipartResolver" <!-- id 的值是固定的-->
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为 5MB -->
        <property name="maxUploadSize">
        <value>5242880</value>
        </property>
    </bean>
    
    

    注意: 文件上传的解析器 id 是固定的,不能起别的名称,否则无法实现请求参数的绑定。(不只是文件,其他 字段也将无法绑定)

    2.2-springmvc跨服务器方式的文件上传

    2.2.1-分服务器的目的

    在实际开发中,我们会有很多处理不同功能的服务器。例如:

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

    (注意:此处说的不是服务器集群)

    分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

    2.2.2-准备两个 tomcat 服务器

    一个作为应用服务器,一个作为文件服务器。

    注意:在文件服务器的 tomcat 配置中(web.xml中)加入,允许读写操作 。

    加入此行的含义是:接收文件的目标服务器可以支持写入操作。

    2.2.3-Maven中导入相关依赖包

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-core</artifactId>
      <version>1.19.4</version>
    </dependency>
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
      <version>1.19.4</version>
    </dependency>
    

    2.3.4-编写控制器实现上传图片

    @Controller
    @RequestMapping("file")
    public class UploadController {
      @RequestMapping("upload02")
      public String fileUpload02(MultipartFile upload) throws IOException {
        System.out.println("SpringMVC跨服务器上传图片");
        // 定义图片服务器上传路径
        String path = "http://localhost:9090/Pro_fileServer_war/uploads/";
        // 获取到上传文件的名称
        String filename = upload.getOriginalFilename();
        // 文件名唯一
        filename = UUID.randomUUID().toString().replaceAll("-","") +"."+ filename.split("\.")[1];
        // 创建客户端对象
        Client client = Client.create();
        // 连接图片服务器
        WebResource resource = client.resource(path + filename);
        // 上传图片
        resource.put(upload.getBytes());
        System.out.println("上传成功");
        return "success";
      }
    }
    

    2.3.5-编写 jsp 页面

    <form action="file/upload02" method="post" enctype="multipart/form-data">
        <input type="file" name="upload" >
        <input type="submit" value="上传图片">
    </form>
    

    2.3.6-配置解析器

    在springMvc配置文件中配置

    <!-- 配置文件解析器对象(上传文件使用),要求id名称必须是multipartResolver -->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760"/>
    </bean>
    

    第三章:SpringMVC中的异常处理

    3.1-异常处理的思路

    ​ 系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息, 后者主要通过规范代码开发、测试通过手段减少运行时异常的发生 。

    ​ 系统的 dao、service、controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端 控制器交由异常处理器进行异常处理,如下图:

    3.2-实现步骤

    3.2.1-编写异常类和错误页面

    /**
     * 自定义异常类
     */
    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;
      }
    }
    

    3.2.2-自定义异常处理器

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

    3.2.3-控制器代码

    @Controller
    @RequestMapping("exception")
    public class ExceptionController  {
      @RequestMapping("test")
      public String test() throws Exception{
        System.out.println("test方法执行了");
        try{
          int a = 10/0;
        }catch (Exception e){
          throw  new SysException("查询错误");
    
        }
        return "success";
      }
    }
    
    

    3.2.4-JSP代码

        <h1>异常</h1>
        <p><a href="exception/test">异常处理</a></p>
    

    第四章:SpringMVC 中的拦截器

    4.1-拦截器的作用

    Spring MVC 的处理器拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。

    用户可以自己定义一些拦截器来实现特定的功能。

    谈到拦截器,还要向大家提一个词——拦截器链(Interceptor Chain)。拦截器链就是将拦截器按一定的顺 序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

    说到这里,可能大家脑海中有了一个疑问,这不是我们用过的过滤器吗?是的它和过滤器是有几分相似,但 是也有区别,接下来我们就来说说他们的区别:

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

    它也是 AOP 思想的具体应用。

    我们要想自定义拦截器, 要求必须实现:HandlerInterceptor 接口。

    4.2-自定义拦截器的步骤

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

    public class HandlerInterceptorDemo1 implements HandlerInterceptor {
       @Override
       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
           System.out.println("preHandle 拦截器拦截了");
           return true;
       }
       @Override
       public void postHandle(HttpServletRequest request, HttpServletResponse response,
       Object handler, ModelAndView modelAndView) throws Exception {
      	 	System.out.println("postHandle 方法执行了");
       }
       @Override
       public void afterCompletion(HttpServletRequest request, HttpServletResponse
    response, Object handler, Exception ex)throws Exception {
       	System.out.println("afterCompletion 方法执行了");
       }
    }
    

    第二步:配置拦截器

    <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/user/*"/>
                <bean class="cn.lpl66.interceptor.HandlerInterceptorDemo1"></bean>
            </mvc:interceptor>
    </mvc:interceptors>
    

    测试运行结果

    preHandle 拦截器拦截了
    controller方法执行了...
    postHandle 方法执行了
    afterCompletion 方法执行了
    

    4.3-拦截器的细节

    4.3.1-拦截器的放行

    放行的含义是指,如果有下一个拦截器就执行下一个,如果该拦截器处于拦截器链的最后一个,则执行控制器 中的方法 。

    4.3.2-拦截器的作用路径

    作用路径可以通过在配置文件中配置。
    <!-- 配置拦截器的作用范围 -->
    <mvc:interceptors>
        <mvc:interceptor>
        <mvc:mapping path="/user/*" /><!-- 用于指定对拦截的 url -->
        <mvc:exclude-mapping path=""/><!-- 用于指定排除的 url-->
        <bean id="handlerInterceptorDemo1" class="cn.lpl66.interceptor.HandlerInterceptorDemo1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    

    4.3.3-多个拦截器的执行过程

    多个拦截器是按照配置的顺序决定的。

  • 相关阅读:
    nginx+tomcat配置websocket反向代理
    jmter 参数化
    postman 自动化
    python yaml文件读写
    python redis 操作
    pycharm 连接github操作
    校验身份证号
    python faker 造数据
    pandas处理日期相关的操作
    python的time几种用法strptime、strftime、localtime、mktime
  • 原文地址:https://www.cnblogs.com/lpl666/p/12364417.html
Copyright © 2011-2022 走看看