美文网首页
SpringMVC学习笔记

SpringMVC学习笔记

作者: 青年心路 | 来源:发表于2019-05-14 19:10 被阅读0次

    一、SpringMVC简介
    1.什么是MVC
    Model:数据模型
    View:视图
    Controller:控制器

    MVC是一种Web应用架构,是一种代码设计思想
    思想:将所有客户端请求交由控制器,由控制器将其进行分发,并将结果响应给客户端。

    2.常见MVC框架
    使用原生Servlet实现MVC:

    • 配置比较复杂
    • 数据处理太麻烦

    实际开发中一般都会使用MVC框架,如Struts1、Struts2、SpringMVC等

    对比:

    • 效率方面,Struts1>SpringMVC>Struts2
      Struts2是多例的,效率低
      Struts1和SpringMVC是单例的,两者效率差不多。
    • 配置方面:SpringMVC>Struts2>Struts1

    3.为什么使用SpringMVC

    • 使用注解来替代xml配置,更简单
    • 是单例的,效率高
    • 用户可以自定义,扩展性好
    • SpringMVC和Spring无缝衔接

    二、SpringMVC实现原理
    1.流程图


    springMVC运行原理

    2.执行过程

    • DispatcherServlet
      SpringMVC核心控制器(前端控制器):主要是用来分发请求的
    • HandlerMapping
      映射处理器:根据请求的url来映射查找到对应的Handler
      Handler就是Controller层的实现类
    • HandlerAdapter
      适配器:用来适配不同的处理器Handler
      处理器有两种实现方式:实现接口、基于注解,所以执行前需要先适配
    • Handler
      处理器:真正用来处理和执行业务,并产生数据模型Model和视图View,
      Handler会将Model和View封装成ModelAndView对象并返回。
    • ViewResolver
      视图解析器:根据视图名称解析成具体的视图,一般多为jsp页面,然后把它封装成View对象并返回。
    • View
      视图:使用具体的视图技术进行渲染,结合Model进行数据展示。
      视图有很多种形式:jsp、freemarker、velocity、excel、pdf等。

    三、第一个SpringMVC程序
    1.添加jar包

            <!--SpringMVC-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
    

    2.配置核心控制器

    <!--配置DispatcherServlet-->
      <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--在web应用启动时执行-->
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    

    3.创建配置文件
    两种定义方式:

    • 使用默认的位置,默认在WEB-INF/目录下,
      名称为:核心Servlet名称-servlet.xml
      例如:springMVC-servlet.xml
    • 自定义位置,名称自定义

    根据Controller实现方式的不同,配置方式也有所不同,有两种方式定义Controller

    • 实现接口
    • 基于注解

    3.1实现接口的Controller

    public class HelloController implements Controller {
        @Override
        public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
            //获取请求信息
            String name = req.getParameter("name");
            ModelAndView mav = new ModelAndView();
            //在ModelAndView中添加属性
            mav.addObject("msg","Hello "+name);
            //指定视图路径
            mav.setViewName("hello");
            //返回
            return mav;
        }
    }
    

    springMVC-servlet.xml

        <!--2.配置HandlerMapping-->
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    
        <!--3.配置HandlerAdapter-->
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
        <!--
            4.配置Handler
            name:访问控制器的url
            class:指定控制器的全限定路径
        -->
        <bean name="/hello" class="controller.HelloController"/>
    
        <!--5.配置ViewResolver-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--指定前缀-->
            <property name="prefix" value="/WEB-INF/view/"/>
            <!--指定后缀-->
            <property name="suffix" value=".jsp"/>
    
            <!--6.配置view,使用jsp视图技术渲染页面-->
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        </bean>
    

    3.2 基于注解的Controller

    @Controller
    public class HelloAnnotationController {
    
        @RequestMapping("/hello")
        public ModelAndView sayHello(String name){
            ModelAndView mav = new ModelAndView();
            mav.addObject("msg","你好 "+name);
            mav.setViewName("hello");
            return mav;
        }
    }
    

    springmvc.xml

        <!--2.配置映射处理器-->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    
        <!--3.配置处理器适配器-->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    
        <!--4.指定Handler-->
        <context:component-scan base-package="controller"/>
    
        <!--5.配置视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置指定前缀和后缀-->
            <property name="prefix" value="/WEB-INF/view/"/>
            <property name="suffix" value=".jsp"/>
            <!--6.配置视图 如果使用的时jsp视图技术,可以省略不写-->
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        </bean>
    

    注意:也可以使用<mvc:annotation-driven/>来省略映射处理器和映射适配器。

    四、静态资源的放行
    当DispatcherServlet的<url-pattern>/</url-pattern>配置为/时,会拦截所有请求,其中包括静态资源。

    问题:因为DispatcherServlet会将静态资源当作Controller,所以会拿到HandlerMapping中去查找。
    解决1:

    • 使用Tomcat提供的默认Servlet
      tomcat提供了默认的Servlet来处理静态资源
        <!--使用Tomcat提供的默认Servlet处理静态资源-->
        <mvc:default-servlet-handler/>
    

    缺点:

    • 如果使用的不是Tomcat,有可能不生效
    • 只能读取webapp下的资源,无法读取WEB-INF下的资源

    解决2:

    • 在SpringMVC配置文件中添加
      <mvc:resources mapping="/img/**" location="/WEB-INF/img/"/>

    2.直接访问jsp页面
    问题:默认不能直接访问WEB-INF下的jsp页面,一般都是在Controller中做转发的映射
    解决:在SpringMVC配置文件中添加如下语句

        <!--直接访问jsp页面,view-name代表想要访问的视图名-->
        <mvc:view-controller path="/userLogin" view-name="login"/>
    

    五、Controller详解
    1.方法的返回值,共有四种类型:

    • ModelAndView:表示返回的是数据模型和视图名
    • String:表示返回的是视图的名字
      三种写法(形式):
      普通字符串-->表示视图名称
      "forward:"+url-->转发
      "redirect:"+url-->重定向
    • void:将请求的url作为视图名称,很少使用
    • Object:表示返回的是数据模型(一般返回的是json数据)

    2.SpringMVC注解


    SpringMVC常用注解

    3.@RequestMapping
    3.1 基本用法
    该注解可以定义在方法上,也可以定义在类上,用来表示层级关系。

    配置URL时以/开头和不以/开头的区别:
    添加/代表从项目的根目录开始访问,不添加/代表从当前位置开始查找。

    3.2 URL的多种写法
    请求映射路径有三种写法:

    • Ant风格
      *:表示单层目录,可以匹配任意字符 ,但是只能在一个层级中
      **:表示多层或单层目录,可以没有字符,“/”也可以没有
      ?:表示单个字符,必须有一个字符
    • Rest风格
      {变量}:表示url中的占位符,可以结合@PathVariable获取值
      {变量:正则}:表示使用正则表达式来限定值的格式
    • 固定写法
      value和path互为别名,值为数组,可以指定多个值

    3.3 根据请求方式来访问
    限定请求方式:GET、POST、PUT、DELETE等

        /**
         * 根据请求方式访问
         */
        @RequestMapping(value = "/test6",method = RequestMethod.GET)
        public String test6(){
            return "hello";
        }
    
    //    @RequestMapping(path = "/user/{id}",method = RequestMethod.GET)
        @GetMapping("/user/{id}")
        public String deleteUser(@PathVariable Integer id){
            System.out.println("delete user id:"+id);
            return "hello";
        }
    
    //    @RequestMapping(path = "/user/{id}",method = RequestMethod.POST)
        @PostMapping("/user/{id}")
        public String selectUser(@PathVariable Integer id){
            System.out.println("select user id:"+id);
            return "hello";
        }
    

    3.4 其他属性

    • params
      限定请求参数,必须符合指定条件
        //请求参数中必须包含id,uname必须为admin,pwd不能是123
        @RequestMapping(path = "/test7",params = {"id","uname=admin","pwd!=123"})
        public String test7(){
            return "hello";
        }
    
    • headers
      限定请求头,必须符合指定条件才能访问url
        //请求头中必须包含Cookie
        @RequestMapping(path = "/test8",headers = {"Cookie"})
        public String test8(){
            return "hello";
        }
    

    六、方法的参数
    1.JavaEE组件

    • HttpServletRequest
    • HttpServletResponse
    • HttpSession
    1. IO流
    • InputStream/OutputStream
    • Reader/Writer
    1. 向界面传递数据
      Model、Map、ModelMap
      将数据存储到request作用域中

    4.String和基本数据类型

    • @RequestParam:
      表示参数值来源于同名请求参数,默认所有参数都添加该注解。
      但是如果手动添加了注解,就必须为参数传值。
      如果不传参数值可以在注解中使用required属性,将值改为false。
      也可以添加defaultValue属性,为参数添加默认值。
    • @PathVariable
      表示参数来源于url
    • @RequestHeader
      表示参数来源于请求头
    • @CookieValue
      表示参数来源于Cookie
    • @RequestBody
      表示参数来源于请求体(只有POST请求才有请求体)

    5.自定义类型
    @ModelAttribute:
    将请求数据转化为对象
    条件:对象的属性名必须与表单元素一致
    @ModelAttribute注解的两种用法

    • 在方法参数前面添加该注解
      作用:将请求参数转换为对象
    • 在方法上面添加该注解
      作用:在调用所有目标方法前都会调用添加@ModelAttribute注解的方法,并向模型中添加数据

    6.错误参数

    • Errors、BindingResult
      用来获取错误信息,实现服务端的数据校验

    实际开发中,既要做客户端表单校验,又要做服务端表单校验

    7、服务器校验框架
    1.简介
    1.1 JSR303校验
    JSR303是一个数据验证的标准规范,用于对JavaBean中的属性进行校验,称为Bean Validation。

    提供了常用的校验的注解
    1.2 Hibernate Validator
    是JSR303的一个参考实现,并提供了扩展注解

    2.用法
    2.1 添加jar包

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate-validator.version}</version>
          </dependency>
    
          <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator-annotation-processor</artifactId>
            <version>${hibernate-validator-annotation-processor.version}</version>
          </dependency>
    

    2.2 为参数对象添加注解
    在需要校验的对象前面添加@Valid注解

    2.3 为对象中的属性添加注解
    示例:

      @NotEmpty(message = "用户名不能为空")
      @Pattern(regexp = "\\w(6,10)",message = "用户名只能包含数字,字母,下划线,且长度为6~10位")
      private String uname;
      
      @Length(min = 6,max = 16,message = "密码长度必须为6~16位")
      private String pwd;
      
      @Pattern(regexp = "(139|133|131)\\d{8}",message = "手机号格式不正确")
      private String phone;
      
      @Email(message = "邮箱格式不正确")
      private String email;
      
      @Range(min = 1,max = 120,message = "年龄必须在1~120之间")
      private int age;
    

    8、类型转换
    1.简介
    数据绑定流程:获取值--->查找转换器--->转换--->后台数据校验--->数据绑定

    两种解决方式:

    • 方式1:使用PropertyEditor
    • 方式2:使用Converter(推荐)

    2.使用PropertyEditor
    步骤:
    - 定义属性编辑器
    - 注册属性编辑器
    @InitBinder

    缺点:

    • 代码是嵌套在Controller层中
    • 只能从字符串转换成相应的对象

    3.使用Converter
    步骤:

    • 定义转换器,实现Converter接口。
    • 配置自定义转换器
        <!--  配置自定义转换器  -->
        <bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <!--将自定义的转换器添加到set集合中-->
                    <bean class="converter.StringToAddressConverter"/>
                    <bean class="converter.AddressToStringConverter"/>
                </set>
            </property>
        </bean>
    
    • 加载自定义转换器
    <mvc:annotation-driven conversion-service="conversionService"/>
    

    9.@SessionAttributes
    作用:将模型中指定名称的数据存储到session中

    10.统一异常处理
    1.简介
    对异常进行统一处理
    两种方式:

    • 使用web技术提供的统一异常处理
    • 使用SpringMVC提供的异常处理

    2.使用web技术的异常处理

      <!--404异常-->
      <error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
      </error-page>
    
      <!--500异常-->
      <error-page>
        <error-code>500</error-code>
        <location>/500.jsp</location>
      </error-page>
    

    3.使用SpringMVC的异常处理
    步骤:
    1.定义一个异常处理类(通知),添加@ControllerAdvice注解
    2.定义异常方法并添加@ExceptionHandler注解

    @ControllerAdvice
    public class ExceptionAdvice {
    
        @ExceptionHandler(ArithmeticException.class)
        public String arithmetic(Exception e){
            System.out.println(e);
            System.out.println("警报!程序出现算数异常"+e.getMessage());
            return "error/arithmetic";
        }
    
        @ExceptionHandler(NullPointerException.class)
        public String nullPointer(Exception e){
            System.out.println(e);
            System.out.println("警报!程序出现空指针异常"+e.getMessage());
            return "error/nullPointer";
        }
    
        @ExceptionHandler(Exception.class)
        public String exception(Exception e){
            System.out.println(e);
            System.out.println("警报!程序出现异常"+e.getMessage());
            return "error/exception";
        }
    }
    

    11.拦截器
    1.简介
    使用Interceptor对请求进行拦截,类似于过滤器Filter

    2.用法
    步骤:
    1.定于一个类,InterceptorHandler
    2.实现接口中的方法
    3.配置拦截器

        <!--注册拦截器-->
        <mvc:interceptors>
            <!--拦截所有请求-->
            <bean class="interceptor.HelloInterceptor"/>
            <!--拦截指定请求-->
            <mvc:interceptor>
                <mvc:mapping path="/user/regist"/>
                <mvc:mapping path="/login"/>
                <bean class="interceptor.RegistInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>
    

    12.处理AJAX
    1.@ResponseBody
    为方法添加该注解中,会将返回值写到响应体中

    2.返回JSON
    三种方式:

    • jackson:SpringMVC默认支持
    • gson:SpringMVC默认支持,google开发
    • fastjson:SpringMVC默认不支持,alibaba开发

    2.1 使用jackson
    步骤:
    1.添加jar包

          <!--处理json-->
          <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson-databind.version}</version>
          </dependency>
    

    2.配置消息转换器(可省略)

        <mvc:annotation-driven conversion-service="conversionService">
            <!--配置消息转换器-->
            <mvc:message-converters>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            </mvc:message-converters>
        </mvc:annotation-driven>
    

    2.2 使用gson
    步骤:
    1.添加jar包

          <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>${gson.version}</version>
          </dependency>
    

    2.配置消息转换器(可省略)

        <mvc:annotation-driven conversion-service="conversionService">
            <!--配置消息转换器-->
            <mvc:message-converters>
                <bean class="org.springframework.http.converter.json.GsonHttpMessageConverter"/>
            </mvc:message-converters>
        </mvc:annotation-driven>
    

    2.3 使用fastjson
    步骤:
    1.引入jar包

          <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
          </dependency>
    

    2.配置消息转换器

        <mvc:annotation-driven conversion-service="conversionService">
            <!--配置消息转换器-->
            <mvc:message-converters>
                <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                    <property name="supportedMediaTypes" value="application/json"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
    

    13.文件的上传单个与多个以及文件下载
    1.单个文件上传
    1.1 简介
    SpringMVC对文件上传提供了支持,基于commons-fileupload

    1.2 用法
    步骤:
    1.添加jar包

          <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>${commons-fileupload.version}</version>
          </dependency>
    

    2.编写上传页面
    注意:因为是上传文件,所以需要使用enctype属性指定上传类型

        <form action="${pageContext.request.contextPath}/file/upload" method="post" enctype="multipart/form-data">
            <input type="file" name="multipartFile"/><br>
            <input type="submit" value="上传"/>
        </form>
    

    3.配置文件解析器
    注意:因为文件使用的是二进制格式,所以需要配置文件解析器

        <!--配置文件解析器 id名称必须为multipartResolver-->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
    

    4.创建Controller
    注意:因为上传的文件数据是从请求参数中来,所以需要添加@RequestParam注解

      @Controller
    @RequestMapping("/file")
    public class FileController {
    
        @RequestMapping("/upload")
        public String upload(@RequestParam CommonsMultipartFile multipartFile) throws IOException {
            System.out.println(multipartFile);
            System.out.println("文件名:"+multipartFile.getOriginalFilename());
            System.out.println("表单名称:"+multipartFile.getName());
    
            //指定上传的位置
            String path = "D:/";
            //获取上传的文件的文件名
            String filename = multipartFile.getOriginalFilename();
            //上传
            multipartFile.transferTo(new File(path,filename));
            return "success";
        }
    }
    

    2.多个文件上传
    步骤:
    1.编写上传页面

        <form action="${pageContext.request.contextPath}/file/upload" method="post" enctype="multipart/form-data">
            <input type="file" name="multipartFiles"/><br>
            <input type="file" name="multipartFiles"/><br>
            <input type="file" name="multipartFiles"/><br>
            <input type="submit" value="上传"/>
        </form>
    

    2.编写Controller

    @Controller
    @RequestMapping("/file")
    public class FileController {
    
        @RequestMapping("/upload")
        public String upload(@RequestParam CommonsMultipartFile[] multipartFiles, HttpSession session) throws IOException {
            //指定上传的位置
            String path = "D:/";
            for (CommonsMultipartFile img : multipartFiles) {
                //获取上传的文件的文件名
                String filename = img.getOriginalFilename();
                //上传
                img.transferTo(new File(path,filename));
            }
            return "success";
        }
    }
    

    3.文件下载
    步骤:
    1.编写下载页面

    <a href="${pageContext.request.contextPath}/file/download">点击下载</a>
    

    2.创建Controller

        @RequestMapping("/download")
        public ResponseEntity<byte[]> download() throws IOException {
            //指定下载文件
            File file = new File("D:/美女.png");
            //通过输入流将文件传入
            FileInputStream is = new FileInputStream(file);
            //创建字节数组,并将数组大小设置为预估的文件字节数
            byte[] bytes = new byte[is.available()];
            //将输入流中的字符存储到缓存数组中
            is.read(bytes);
            //获取下载显示的文件名,并解决中文乱码
            String name = file.getName();
            String downloadFileName = new String(name.getBytes("UTF-8"), "ISO-8859-1");
            //设置Http响应头信息,并且通知浏览器以附件形式进行下载
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Content-Disposition","attachment;filename="+downloadFileName);
            //设置Http响应状态信息  OK代表正常
            HttpStatus status = HttpStatus.OK;
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, httpHeaders, status);
            return responseEntity;
        }
    

    相关文章

      网友评论

          本文标题:SpringMVC学习笔记

          本文链接:https://www.haomeiwen.com/subject/dcwioqtx.html