美文网首页JavaWeb框架&JavaWeb工具学习
SpringMVC(一)基本原理、使用、参数接收

SpringMVC(一)基本原理、使用、参数接收

作者: So_ProbuING | 来源:发表于2019-12-12 18:27 被阅读0次

    MVC模式

    MVC指的是模型(model)-视图(view)-控制器(controller)模型,是一种用于设计创建Web应用程序表现层的模式。可以将业务逻辑、数据、界面显示代码分离开来。

    image.png
    • 三层架构-mvc


      image.png

    SpringMVC

    SpringMVC是Spring产品对MVC模式的一种具体实现,属于轻量级的WEB框架,可以通过一套注解,让一个简单的Java类称为控制器。而无须实现任何接口,同时还支持restful风格


    image.png

    SpringMVC主要工作的组件有:

    • 前端控制器
    • 处理器映射器
    • 处理器适配器

    SpringMVC入门案例

    • 加入坐标
     <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.1.6.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
                <scope>provided</scope>
    
            </dependency>
    
    
        </dependencies>
    
    • SpringMVC配置文件 spring-mvc.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        <!--    配置注解扫描-->
        <context:component-scan base-package="com.itheima.controller"/>
        <!--    配置组件-->
        <!--    配置处理器映射器和处理器适配器-->
        <mvc:annotation-driven/>
        <!--    配置视图解析器-->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean>
    </beans>
    
    • web.xml
    <?xml version="1.0" encoding="utf-8"?>
    <web-app version="3.0"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
        <servlet>
            <servlet-name>dispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--        配置参数-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>dispatcherServlet</servlet-name>
            <!--        除了jsp不拦截-->
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    
    • 后端controller
    @Controller
    public class HelloController {
        @RequestMapping("/helloServlet/demo1")
        public String demo1() {
            System.out.println("hello1");
            return "/success.jsp";
        }
    }
    
    • 请求页面
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <a href="${pageContext.request.contextPath}/helloServlet/demo1">入门案例</a>
    
    </body>
    </html>
    
    • 响应页面
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    Success
    </body>
    </html>
    

    SpringMVC原理

    image.png
    • 当用户通过浏览器发送一个请求会被前端控制器DispatcherServlet接收
    • DispathcerServlet接收请求后会调用处理器映射器HandlerMapper
    • HandlerMapper会找到具体的处理器链返回给DispatcherServlet
    • DispatcherServlet会根据收到返回的处理器链调用处理器适配器HandlerAdapter
    • HandlerAdapter经过适配后会调用具体的Controller
    • Controller执行完成后会返回一个执行结果
    • HandlerAdapter将Handler的结果ModelAndView对象返还给DispatcherServlet
    • DispatcherServlet将ModelAndView对象传给视图解析器ViewReslover
    • ViewReslover解析后得到具体的View,并返回给DispatcherServlet
    • DispatcherServlet根据ViewReslover返回的View进行视图渲染。将模型数据填充到视图中
    • DispathcerServlet会将渲染后的视图响应给浏览器

    SpringMVC三大组件

    • 处理器映射器 HandlerMapper

    根据请求中的URL寻找对应的处理方法

    • 处理器适配器

    真正的去调用处理方法

    • 视图解析器

    将逻辑视图转化成物理视图

    配置视图解析器

     <!--    配置视图解析器-->
        <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--        配置前缀-->
            <property name="prefix" value="/"/>
    <!--        配置后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    

    RequestMapping

    RequestMapping用于建立请求URL和处理方法之间的对应关系,可以通过它的属性对请求做出各种限制

    • value:用于限制请求URL(和path作用一样),可以传递多个url @RequestMapping(value={url1,url2})
    • method:用于限制请求类型 get post 支持多个,如果不写表示不做限制
    • Params:用于限制请求参数的条件 用于限制必传参数,支持数组
    @RequestMapping("/helloServlet/demo1")
        public String demo1() {
            System.out.println("hello1");
            return "success";
        }
    

    此注解可以标注在方法上,也可以标注在类上,标注在类上代表类中的所有方法都可以共用一段URL

    限制请求路径(value path)

    • 前台页面
    <a href="${pageContext.request.contextPath}/helloServlet/demo2">指定请求路径</a>
    
    
    • 后台
    @RequestMapping("/helloServlet/demo2")
        public String demo2() {
            System.out.println("指定请求路径为:/helloServlet/demo2");
            return "success";
        }
    

    限制请求类型(method)

    限制只能是post方式请求,如果不是指定的请求方式 将会抛出405异常

    • 页面
    <form action="helloServlet/demo3" method="post">
        <input type="submit" value="限制请求方式">
    </form>
    
    • 后台
     @RequestMapping(value = "/helloServlet/demo3",method = RequestMethod.POST)
        public String demo3() {
            System.out.println("限制请求类型");
            return "success";
        }
    

    限制请求参数(params)

    • 页面
     <a href="${pageContext.request.contextPath}/helloServlet/demo4?name=zs">指定请求的参数</a>
    
    
    • 后台

    表示必须传递name参数

     @RequestMapping(value = "/helloServlet/demo4", params = "name")
        public String demo4() {
            return "success";
        }
    

    接收请求参数

    在SpringMVC中可以使用多种类型来接收前端传入的参数

    简单类型

    基本类型、基本类型的包装类、字符串类型

    只需要保证前端传递的参数名称跟方法的形参名称一致就好

    • 页面
    <a href="${pageContext.request.contextPath}/helloServlet/demo5?name=zs&age=18">接收简单类型参数</a>
    
    
    • 后台
    @RequestMapping(value = "/helloServlet/demo5")
        public String demo5(String name, Integer age) {
            System.out.println("name = " + name);
            System.out.println("age = " + age);
            return "success";
        }
    

    对象类型

    只要保证前端传递的参数名称和pojo的属性名称(set方法)一致

    • 前台
    <a href="${pageContext.request.contextPath}/helloServlet/demo6?name=ss&age=20">接收对象类型</a>
    
    
    • 后台
     @RequestMapping("/helloServlet/demo6")
        public String demo6(User user) {
            System.out.println("user = " + user);
            return "success";
        }
    

    数组类型

    需要保证前端传递的参数名称和方法中的数组形参名称一致

    • 页面
    <a href="${pageContext.request.contextPath}/helloServlet/demo7?username=zz&username=zz2&username=zz3">传递数组类型</a>
    
    
    • 后台
       @RequestMapping("/helloServlet/demo7")
        public String demo7(String[] username) {
            for (String s : username) {
                System.out.println(s);
            }
            return "success";
        }
    

    集合类型

    获取集合类型的参数时,需要提供一个pojo对象,SpringMVC会将集合包装到pojo对象中

    • 页面
    <form action="${pageContext.request.contextPath}/helloServlet/demo8" method="post">
        第一个user.name <input type="text" name="users[0].name"/><br/>
        第一个user.age <input type="text" name="users[0].age"/><br/>
        第二个user.name <input type="text" name="users[1].name"/><br/>
        第二个user.age <input type="text" name="users[1].age"/><br/>
        第三个user.name <input type="text" name="users[2].name"/><br/>
        第三个user.age <input type="text" name="users[2].age"/><br/>
        <input type="submit" value="传递集合"/>
    </form>
    
    • 封装vo对象
    public class Vo {
        private List<User> users;
        private Map<String, String> map;
    
        @Override
        public String toString() {
            return "Vo{" +
                    "users=" + users +
                    ", map=" + map +
                    '}';
        }
    
        public void setUsers(List<User> users) {
            this.users = users;
        }
    
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
    }
    
    • 后台controller
     @RequestMapping("/helloServlet/demo8")
        public String demo8(Vo vo) {
            List<User> users = vo.getUsers();
            users.stream().forEach(user -> System.out.println(user));
            return "success";
        }
    

    日期类型

    对于一些常见的类型,SpringMVC是内置了类型转换器,也就是说在内置中存在一个类型转换器,可以自动转换基本类型,但是对于一些类型的参数,无法完成类型转换。这时候就必须自定义类型转换器了

    • 页面
    • 自定义时间类型转换器

      自定义类型转换器需要实现Converter<S,D>接口

      • S:代表需要转换的源Source类型
      • D:代表转换后的目标类型
    public class DateConverter implements Converter<String, Date> {
        @Override
        public Date convert(String s) {
            return new SimpleDateFormat("yyyy-MM-dd").parse(s);
        }
    }
    
    • 配置类型转换器 spring-mvc.xml

    将自定义的类型转换器注册SpringMVC的转换服务,并且将服务注册到注解驱动上

     <mvc:annotation-driven conversion-service="conversionService2"/>
        <!--    配置视图解析器-->
        <!--    配置自定义类型转换器-->
        <bean id="conversionService2" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <set>
                    <!--                指定自定义类型转换器-->
                    <bean class="com.itheima.converters.DateConverter"/>
                </set>
            </property>
        </bean>
    
    • 后台
      @RequestMapping("/helloServlet/demo9")
        public String demo9(Date date) {
            System.out.println(date);
            return "success";
        }
    

    文件类型(文件上传)

    • 配置文件上传用的坐标
    <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.4</version>
            </dependency>
    
    • 配置文件上传解析器

      <!--    配置文件解析器-->
      <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
          <property name="maxUploadSize" value="5242880"/>
      </bean>
      
    • 页面

      • post提交
      • 多部分表单 part-form
      • type=file
    <%--文件上传--%>
    <form action="${pageContext.request.contextPath}/helloServlet/demo10" method="post"
          enctype="multipart/form-data"
    >
        <input type="file" name="upFile"/><br/>
        <input type="submit" value="上传">
    </form>
    
    • 后台
    @RequestMapping("/helloServlet/demo10")
    public String demo10(MultipartFile upFile) throws IOException {
        //获取名字 重新命名
        String newFileName = UUID.randomUUID() + upFile.getOriginalFilename();
        String saveFilePath = "/Users/wangxin/Documents/temp";
        File uploadFile = new File(saveFilePath, newFileName);
        //接收上传文件
        upFile.transferTo(uploadFile);
        return "success";
    }
    

    多文件上传

    • 页面

    多文件上传 需要在<input type="file">标签中添加multiple属性

    多文件上传:
    <form method="post" action="${pageContext.request.contextPath}/helloServlet/demo11" enctype="multipart/form-data">
        <input type="file" multiple/>
        <input type="submit" value="提交">
    </form>
    
    • 后台 多文件上传 后台需要接收MultiPartFile数组
    @RequestMapping("helloServlet/demo11")
    public String demo11(MultipartFile[] upFiles) throws IOException {
        String saveFilePath = "/Users/wangxin/Documents/temp";
    
        for (MultipartFile file : upFiles) {
            String newFileName = UUID.randomUUID() + file.getOriginalFilename();
            File uploadFile = new File(saveFilePath, newFileName);
            //文件上传
            file.transferTo(uploadFile);
        }
        System.out.println("文件上传完毕");
        return "success";
    }
    
    文件上传原理

    在前端控制器(DispatcherServlet)有一个属性叫做multipartResolver,它对应着一个文件上传解析器

    当SpringMVC启动的时候,它就会在容器中寻找是否有一个id位multipartResolver的bean,如果有那么会将文件上传的文件交给指定的文件解析器来做。

    当DispathcerServlet调用controller方法的时候就可以将MultipartFile作为参数传进去了

    在Controller中就可以操作MultiPartFIle对象进行文件的操作

    接收参数的处理

    中文乱码

    SpringMVC在使用POST提交请求时,对于中文参数会存在乱码问题,我们可以使用SpringMVC提供的中文乱码过滤器

    • 前端

    通过form表单的post请求提交中文

    <%--提交中文乱码--%>
    <br/>
    <form action="${pageContext.request.contextPath}/helloServlet/demo12" method="post">
        姓名:<input type="text" name="username"/>
    </form>
    
    
    • 配置 编码过滤器
        <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>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    • 后台

    • @RequestMapping("/helloServlet/demo12")
      public String demo12(String username) {
          System.out.println("接收到的参数:" + username);
          return "success";
      }
      
    @RequestParam

    @RequestParam标注在方法参数之前,用于对传入的参数做一些限制,支持三个属性:

    • Value:用于指定前端传入的参数名称
    • required:用于指定此参数是否必传,默认是true
    • defaultValue:当参数为非必传参数设置一个默认值
    • 前台
    <a href="${pageContext.request.contextPath}/helloServlet/demo13?username=达到">前端参数对应</a>
    
    
    • 后台
     @RequestMapping("/helloServlet/demo13")
        public String demo13(@RequestParam("username") String name) {
            System.out.println(name);
            return "success";
        }
    

    接收请求头信息

    接收请求头,使用

    • @RequestHeader 前端控制器会将所有的请求头封装成一个Map结构传递过来
    • @RequestHeader("key") 接收指定的请求头
    • @CookieValue("key") 接收一个Cookie中的值
    @RequestMapping("/helloServlet/demo14")
        public String demo14(
                @RequestHeader Map<String, String> headMap,
                @RequestHeader("cookie") String cookieKey,
                @CookieValue("JSESSIONID") String jSessionId
        ) {
            System.out.println(headMap);
            System.out.println(cookieKey);
            System.out.println(jSessionId);
            return "success";
        }
    

    相关文章

      网友评论

        本文标题:SpringMVC(一)基本原理、使用、参数接收

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