简单了解SpringMVC(五)

SpringMVC概述

  • 介绍
  1. Spring为展现层提供的基于MVC设计理念的优秀web框架.
    • MVC封装了Servlet
    • M: 模型层, 指项目中实体类JavaBean, 装载并传输数据.
    • V: 视图层.
    • C: 控制层: 代表Servlet.
  2. SpringMVC通过一套MVC注解, 让POJO成为处理请求的控制器, 而无需实现任何接口.
    • POJO: 就是最基本的Java对象.
  3. 支持REST风格的URL请求.
  4. 采用了松散耦合可插拔组件结构, 比其他MVC更具有扩展性和灵活性.
  • SpringMVC是什么
  1. 轻量级, 基于MVC的web层应用框架, 偏前端而不是基于业务逻辑层, Spring框架的一个后续产品.
  • SpringMVC能干什么
  1. 天生与Spring框架集成, 如(IOC, AOP)
  2. 进行更简洁的Web层开发.
  3. 支持灵活的URL到页面控制器的映射.
  4. 非常容易与其他视图技术集成, 如:Velocity, FreeMarker等.
  5. 因为数据模型不存在特定的API里, 二十放在一个Model里(Map数据结构实现), 所以很容易i被其他框架使用.
  6. 非常灵活的数据验证, 格式化和数据绑定机制, 能使用任何对象进行数据绑定, 不用实现特定框架的API
  7. 更简单, 强大的异常处理.
  8. 对静态资源的支持.
  9. 支持灵活的本地化, 主题等解析.
  • SpringMVC怎么用
  1. 将Web层进行了职责解耦, 基于请求 - 响应模型
  2. 常用组件
    • DispatcherServlet: 前端控制器
      • 对客户端发送的请求统一管理的.
    • Controller: 处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理.
    • HandlerMapping: 请求映射到处理器,找谁来处理, 如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象, 多个HandlerInterceptor拦截器对象).
    • View Resolver: 视图解析器,找谁来处理返回的页面。把逻辑视图解析为具体的View,进行这种策略模式,很容易更换其他视图技术.
      • 如: InternalResourceViewResolver将逻辑视图名映射为JSP视图.
    • LocalResolver: 本地化, 国际化
    • MultipartResolver: 文件上传解析器.
    • HandlerExceptionResolver: 异常处理器.
  • 案例
  1. 创建maven的Web工程, 并加入如下依赖
    <properties>
            <spring.version>5.0.8.RELEASE</spring.version>
    </properties>
    
    <dependencies>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>${spring.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>${spring.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>${spring.version}</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring.version}</version>
        </dependency>
    </dependencies>
  2. 在web.xml中配置SpringMVC的核心(前端)控制器-DispatcherServlet
    • 作用: 加载springMVC的配置文件, 在如下的配置方式下, 核心配置器会自动加载配置文件, 此时的配置文件有默认的位置和名称(和servlet-name)相同. 为WEB-INF/<servlet-name>-servlet.xml
      • 当然, 我们也可以手动设置SpringMVC配置文件的位置.
        <servlet>
                <servlet-name>springMVC</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <!-- 配置DispatcherServlet的初始化參數:设置文件的路径和文件名称 -->
                <init-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>classpath:springmvc.xml</param-value>
                </init-param>
                <load-on-startup>1</load-on-startup>
            </servlet>
            <servlet-mapping>
                <servlet-name>springMVC</servlet-name>
                <!-- 路径模型 -->
                <url-pattern>/</url-pattern>
            </servlet-mapping>
    • 当加载了配置文件, SpringMVC会根据扫描组件找到控制层
          <!--  扫描组件, 将加@Controller注解的类作为SpringMVC的控制层  -->
          <context:component-scan base-package="test"></context:component-scan>
      
          <!--
              配置视图解析器
              作用: 将prefix + 视图名称 + suffix确定最终要跳转的页面
              /view/xxx.jsp 
           -->
          <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix" value="/WEB-INF/view/"></property>
              <property name="suffix" value=".jsp"></property>
          </bean>
  3. 创建一个POJO, 在此类上加上@Controller注解, springMVC就会将此类作为控制层加载, 让其处理请求响应.
  4. 在控制层中, 需要在方法上设置@RequestMapping(value="href地址"), springMVC就是通过此注解将请求路径与控制层中的方法进行匹配. 
    • 此时请求路径为localhost:8080/projectName/xxx
      index.jsp
      
      <body>
          <a href="hello?username=admin&password=123456">测试SpringMVC</a>
      </body>
      
      /WEB-INF/view/success.jsp
      
      <body>
          SUCCESS
      </body>
    • handler方法
      @Controller
      public class TestController {
      
          @GetMapping(value = "hello")
          public String hello(String username, String password) {
              System.out.println(username);
              System.out.println(password);
              return "success";
          }
      }

      处理请求的方法会返回一个字符串, 即视图名称, 最终会通过配置文件配置的视图解析器来实现页面跳转

RequestMapping详解

  • @RequestMapping注解参数
  1. @RequestMapping: 设置请求映射, 把请求和控制层中的方法设置映射关系.
  2. @RequestMapping可以加在方法上, 也可以加在类上.
    • 若类和方法上都有, 应一层一层的访问, 先访问类, 再访问类中的方法.
  3. value属性
    • 当请求路径和@RequestMapping的value属性一致时, 则该注解所标注的方法即为处理请求的方法.
  4. method属性
    • method: 用来设置请求方式, 只有客户端发送请求的方式和method的值一致, 才能处理请求.
    • 请求方式常用4种
      • RequestMethod.GET: 查询
      • RequestMethod.POST: 添加
      • RequestMethod.PUT: 修改
      • RequestMethod.DELETE: 删除
  5. params: 用来设置客户端传到服务器的数据(请求参数), 支持表达式
    • //value这里, 加斜线是访问项目下, 不加则是访问当前目录下
          @PostMapping(value = "/test", params = {"username", "!age"})
          public String testPOST() {
              System.out.println("SUccess: post");
              return "success";
          }
  6. headers: 用来设置请求头信息, 所发送的请求的请求头信息一定要和headers属性中所设置的一致.
    • //此时, 浏览器中request header的language必须以q=0.8,en-us开头, 否则404错误
      @PostMapping(value = "/test", headers = {"Acceept-Language:q=0.8,en-US;"})
  • @RequestMapping支持Ant路径风格
  1. Ant风格资源地址支持3种匹配符
    • @GetMapping(value = "/*/ant??/**/testAnt")  
      
      匹配
      /aa/antBB/CCC/DDD/testAnt
  • SpringMVC支持占位符方式的路径
  1. @PathVariable
    • 带占位符的url是spring3.0新增, 该功能在SpringMVC向REST目标挺进发展过程具有里程碑意义.
    • 通过@PathVariable可以将URL中占位符参数绑定到控制器处理方法的入参中.
    • 格式: @PathVariable("xxx") 类型 参数名
      <a href="testREST/1001/admin">测试</a>
      //以前: <a href="testREST?id=1001&useranme=admin>测试</a>
      

      @GetMapping("/testREST/{id}/{username}") public String testREST(@PathVariable("id")Integer id, @PathVariable("username")String useranme) { System.out.println(id); System.out.println(useranme); return "success"; }

REST介绍

  • 什么是REST
  1. REST: Representational State Transfer
    • (资源)表观层状态转换, 是目前最流行的互联网软件架构.
    • 资源(Resources): 网络上的一个实体, 或一个具体信息.
      • 可以用一个URL指向它: 每种资源对应一个特定的URI获取这个资源, 访问它的URI就可以, 因此URI即为每一个资源的独一无二的识别符.
    • 表现层(Representation): 把资源具体呈现出的形式, 叫做它的表现层.
      • 比如: 文本以txt格式表现, 也可以用html表现, 甚至二进制表示.
    • 状态转换(State Transfer): 每发出一个请求, 就代表客户端和服务器的一次交互过程.
    • HTTP 协议, 是一个无状态协议, 即所有的状态都保存在服务器端. 因此, 如果客户端想要操作服务器, 必须通过某种手段, 让服务器端发生"状态转化",而这种转化是建立在表现层之上的, 所以就是"表现层状态转化".
      • 具体说, 就是HTTP协议里面, 四个表示操作方式的动词: GET, POST,PUT, DEL它们分别对应四种基本操作: GET用来获取资源, POST用来新建资源, PUT用来更新资源, DELETE用来删除资源.
  2. URL风格
    • 增删改查
  • HiddenHTTPMethodFilter
  1. 浏览器只支持GET与POST请求, 而DELETE, PUT等method并不支持, Spring3.0添加了一个过滤器, 可以将这些请求转换为标准的http方法, 使得支持GET, POST,PUT, DELETE请求.
  2. 由于使用了HiddenHTTPMethodFilter, 所以要在web.xml中配置过滤器
        <filter>
            <filter-name>HiddenHttpMethodFilter</filter-name>
            <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>HiddenHttpMethodFilter</filter-name>
            <!-- 过滤所有 -->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
  3. 分析
    • 该类负责解析隐藏的HttpMethod, 用了该Filter后, 可以在页面上POST时指定 _method参数, 该Filter会根据参数指定的值将Request包装为指定的HttpMethod的request. 
  4. 代码
    • rest.jsp
          <!-- 测试Get -->
          <a href="testREST/1001">测试GET</a>
      
          <!-- 测试POST -->
          <form action="testREST" method="post">
              <input type="submit" value="测试POST">
          </form>
      
          <!-- 测试PUT -->
          <form action="testREST" method="post">
              <input type="hidden" name="_method" value="PUT">
              <input type="submit" value="测试PUT">
          </form>
      
          <!-- 测试DELETE -->
          <form action="testREST" method="post">
              <input type="hidden" name="_method" value="DELETE">
              <input type="submit" value="测试DELETE">
          </form>
    • RESTController.java
      @Controller
      public class TestController {
      
          @GetMapping("/testREST/{id}")
          public String getUserById(@PathVariable("id") Integer id) {
              System.out.println(id);
              return "success";
          }
      
          @PostMapping("/testREST")
          public String insertUser() {
      
              return "success";
          }
      
          @PutMapping("/testREST")
          public String updateUser() {
              return "success";
          }
      
          @DeleteMapping("/testREST/{id}")
          public String deleteUserById(@PathVariable("id")Integer id) {
              System.out.println(id);
              return "success";
          }
      }
      • 但直接这么写, PUT和DELETE会报错, 因为发起的请求是个RESTFul风格的请求, 调用了RESTFul风格的PUT方法, 但是controller里testRestPUT返回的success字符串被映射到success.jsp, 因此spring认为这应该是个JSP接口, 且JSP接口仅仅支持GET方法和POST方法. 
    • 解决方法: 
      • @ResponseBody, 在两个负责处理Delete请求和put请求的controller头部添加.
        • 但只能显示出return的值, 无法转发.
              @ResponseBody
              @PutMapping("/testREST")
              public String updateUser() {
                  return "success";
              }
      • 使用Redirect重定向
            @DeleteMapping("/testREST/{id}")
            public String deleteUserById(@PathVariable("id")Integer id) {
                System.out.println(id);
                return "redirect:/tosuccess";
            }
        
            @GetMapping("/tosuccess")
            public String toSuccess() {
                return "success";
            }

处理请求数据

  • 请求数据
  1. 请求参数, Cookie信息, 请求头信息等.
  2. 在JavaWeb中, HttpServletRequest
    • Request.getParameter(参数名);   Request.getParameterMap(); 
    • Request.getCookies(); Request.getHeader();
  • 请求处理方法签名
  1. SpringMVC通过分析处理方法的签名(方法名+参数列表), Http请求信息绑定到
    处理方法的相应形参中.
  2. SpringMVC对控制器处理方法签名的限制是很宽松的, 几乎可以按喜欢的任何方
    式对方法进行签名.
  3. 可对方法及其参数标注相应注解(@PathVariable, @RequestParam@RequestHeader等)
  4. SpringMVC框架会将Http请求的信息绑定到相应的方法入参中, 并根据方法的返回值类型做出相应的后续处理.
  • @RequestParam注解
  1. 在处理方法入参处使用@RequestParam可以把请求参数传递给请求方法
    • 在请求处理的方法中, 加入相对应的形参, 保证形参参数名和传递数据的参数名保持一致, 就可以自动赋值.
  2. 参数
    • value: 当不满足赋值条件时, 可以使用value属性, 指定映射关系.
    • required: 设置形参是否必须被赋值, 默认为true, 必须赋值, 否则报错. 若设置为false, 则不必赋值.
    • defaultValue: 若形参所获得的值为null, 则设置一个默认值, 用在分页和模糊查询等.
  3. 示例
    • param.jsp
          <form action="param" method="post">
              username: <input type="text" name="name"> <br/>
              password: <input type="password" name="password"> <br/>
          </form>
    • TestController.java
          @PostMapping("/param")
          public String param(@RequestParam(value = "name", required = false, defaultValue = "admin")String username, String password) {
              System.out.println(username);
              System.out.println(password);
              return "success";
          }
  •  @RequestHeader和CookieValue
  1. @RequestHeader
    • 在处理请求的方法上, 获取请求头信息, 用法和@RequestParam一致.
          @PostMapping("/param")
          public String param(@RequestHeader("Accept-Language")String lan) {
              System.out.println(lan);
              return "success";
          }
  2. @CookieValue
    • 在处理请求方法上, 获取cookie信息, 用法和@RequestParam一致.
          @PostMapping("/param")
          public String param(@CookieValue("JSESSIONID")String JESSIONID) {
              System.out.println(JESSIONID);
              return "success";
          }
  •  使用POJO作为参数对象
  1. 可以使用POJO获取客户端数据, 要求实体类对象中的属性名一定要和页面中表单元素的name属性值一致, 且支持级联关系.
  2. 示例
    • Address.java
      @NoArgsConstructor
      @AllArgsConstructor
      @Data
      public class Address {
      
          private String province;
          private String city;
          private String country;
      }
    • param.jsp
          <form action="param" method="post">
              province: <input type="text" name="province"> <br/>
              city: <input type="text" name="city"> <br/>
              country: <input type="text" name="country"/>
              <input type="submit" value="添加">
          </form>
    • TestController.java
          @PostMapping("/param")
          public String param(Address address) {
              System.out.println(address);
              return "success";
          }
  •  使用Servlet原生API作为参数
  1. MVC的Handler方法可以接受九种ServletAPI类型的参数
    • HttpServletRequest
    • HttpServletResponse
    • HttpSession
    • java.security.Principal
    • Locale    
    • InputStream
    • OutputStream
    • Reader
    • Writer
          @Autowired
          private HttpServletRequest request;
      
          @PostMapping("/param")
          public String param() {
              request.getParameter("country");
              return "success";
          }
  2. 记得一定要加servlet依赖
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>

处理响应数据

  • JavaWeb中
    • request.setAttribute(xxx)
    • request.getRequestDispatcher("地址").forward(req, resp)
  • SpringMVC输出模型数据概述
  1. 两种输出模型数据
    • ModelAndView: 处理方法返回值类型为ModelAndView时, 方法体即可通过该对象添加模型数据.
    • Map或Model, 入参为org.springframework.ui.Model, org.springframework.ui.ModelMap 或 java.uti.Map时, 处理方法返回时, Map中的数据会自动添加到模型中.
  • ModelAndView
  1. 介绍
    • 控制器处理方法的返回值如果为ModelAndView, 则其既包含视图信息, 也包含模型数据信息.
    • 两个重要的成员变量
      • private Object view  视图信息
      • private ModelMap model   模型数据
    • 添加模型数据
      • MoelAndView addObject(String attributeName, Object attributeValue)  往request作用域中放值
      • ModelAndView addAllObject(Map<String, ?> modelMap)
    • 设置视图
      • void setView(View view)  设置视图对象
      • void setViewName(String viewName)  设置视图名称
    • 获取模型数据
      • protected Map<String, Object> getModelInternal()
      • public ModelMap getModelMap()
  2. 示例
    • Controller方法
          @PostMapping("/param")
          public ModelAndView param() {
              ModelAndView mav = new ModelAndView();
              mav.addObject("useranme", "root"); //往request域中放值
              mav.setViewName("success");
              return mav;
          }
    • success.jsp
      <body>
          SUCCESS
      
          ${requestScope.username}
      </body>
  • Map和Model
  1. Map介绍
    • SpringMVC 在内部使用了一个org.springframework.ui.Model接口存储模型数据具体使用步骤.
    • SpringMVC 在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器.
    • 如果方法的入参为 Map 或 Model 类型, SpringMVC会将隐含模型的引用传递给这些入参.
    • 在方法体内, 开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据.
  2. 代码
        @PostMapping("/param")
        public String param(Map<String, Object> map) {
    
            map.put("username", "admin");
            return "success";
        }
    
        @PostMapping("/param1")
        public String param1(Model model) {
            model.addAttribute("username", "张三");
            return "success";
        }
原文地址:https://www.cnblogs.com/binwenhome/p/13037790.html