zoukankan      html  css  js  c++  java
  • SpringMVC02


    title: SpringMVC02
    date: 2020-03-11 21:48:52
    tags:


    这里是SpringMVC的所有知识点了。

    基本骨架

    依赖包

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    

    配置文件

    • 首先是web.xml,因为springMVC的底层是servlet,所以要在xml中配置。

      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
               version="4.0">
      
          <!--    注册前端控制器-->
          <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-servlet.xml</param-value>
              </init-param>
              <!--        设置启动级别-->
              <load-on-startup>1</load-on-startup>
          </servlet>
      
      
          <!--    url-pattern
              / : 拦截所有的请求,但不包括jsp
              /* :拦截所有的请求,包括jsp
          -->
          <servlet-mapping>
              <servlet-name>springmvc</servlet-name>
              <url-pattern>/</url-pattern>
          </servlet-mapping>
      
          <!--spring官方的过滤器-->
          <filter>
              <filter-name>encoding</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>encoding</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>
      
      
      </web-app>
      

      (注意的是,servlet-pattern要为 “ / ”)

    • 既然web.xml中配置了依赖的springmvc配置文件,那么就要在src---main---resources中添加springmvc的配置文件了,文件名可以随意,不过要和web.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
                                 https://www.springframework.org/schema/context/spring-context.xsd
                                 http://www.springframework.org/schema/mvc
                                 https://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
          <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
          <context:component-scan base-package="com.annotation.controller"/>
          <!-- 让Spring MVC不处理静态资源 -->
          <mvc:default-servlet-handler />
          <!--
          支持mvc注解驱动
              在spring中一般采用@RequestMapping注解来完成映射关系
              要想使@RequestMapping注解生效
              必须向上下文中注册DefaultAnnotationHandlerMapping
              和一个AnnotationMethodHandlerAdapter实例
              这两个实例分别在类级别和方法级别处理。
              而annotation-driven配置帮助我们自动完成上述两个实例的注入。
           -->
          <mvc:annotation-driven>
              <mvc:message-converters register-defaults="true">
                  <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                      <constructor-arg value="UTF-8"/>
                  </bean>
                  <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                      <property name="objectMapper">
                          <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                              <property name="failOnEmptyBeans" value="false"/>
                          </bean>
                      </property>
                  </bean>
              </mvc:message-converters>
          </mvc:annotation-driven>
      
      
      
          <!-- 视图解析器 -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
                id="internalResourceViewResolver">
              <!-- 前缀 -->
              <property name="prefix" value="/WEB-INF/jsp/" />
              <!-- 后缀 -->
              <property name="suffix" value=".jsp" />
          </bean>
      
      </beans>
      

      这个配置文件已经是完全版的了。

      支持mvc注解驱动就是<mvc:annotation-driven />

      不过这里为了解析json乱码在其中配置了一些东西,需要注意的是如果要解决全局json乱码,除了这个配置之外还要下载Jackson的包。

    controller

    原始的写法

    这里简单说一下最原始的写法,最原始的写法是实现Controller接口,这样该类就有Controller的功能了,然后实现其中的方法:

    package com.mvc.controller;
    
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class helloController implements Controller {
        public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
            ModelAndView modelAndView = new ModelAndView();
    
            //        1.处理业务
            String res = "hello,my first springmvc demo!!";
            //        2.放入模型
            modelAndView.addObject("msg",res);
            //        3.封装要跳转的视图
            modelAndView.setViewName("test");
    
            return modelAndView;
        }
    }
    
    

    需要注意的是,因为是原始的写法,所以springmvc的配置文件中需要注册:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           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">
    
        <!--    注册处理映射器-->
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        <!--    注册处理适配器-->
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    
        <!--    添加视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
            <!--        设置解析前缀-->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!--        设置解析后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
        <!--    注册controller-->
        <bean id="/hello" class="com.mvc.controller.helloController"/>
    
    </beans>
    

    当今的写法

    当今的写法当然是使用注解了,需要用到如下注解:

    • @Controller :在类上使用该注解表明该类是一个Controller
    • @RequestMapping("/xxx") :在方法上使用该注解,并为其写一个请求的名字,相当于servlet的名字,重点是记得写引号中的 **/ ** !!!!

    以下是一个小例子:

    package com.annotation.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class encodingController {
    
        @RequestMapping("/encoding")
        public String test(String name, Model model){
            //将name的值存入msg中
            model.addAttribute("msg",name);
            return "hello";
        }
    }
    
    • 用注释的话,方法要接收的的参数名称需要与前端传来的数据名称相同,不过在真实开发中应该一个注释:@RequestParam("name") String name。一方面可以保持与前端数据的一致性,另一方面可以清楚的分辨出哪些参数是前端传过来的,哪些是后端的。

    • 以往的servlet传递数据都是使用request的set方法将传递的数据存放到域中,此时我们使用model来传递。

    • 如果要接收一个对象,那么前端传递过来的应该是对象的各个属性,此时直接将对象作为参数即可,springmvc框架也可以为我们解析。

      如一个User类(属性有id,name,age):

      @RequestMapping("/object")
      public String test(User user, Model model){
          //将name的值存入msg中
          model.addAttribute("msg",user.name);
          return "hello";
      }
      

      那么前端传递过来的url地址应该是:

      ip地址/项目名称/object?id=1&name=小王&age=10
      

    既然我们传递了参数,那么接下来当然是转发到我们数据需要送往的视图了,怎么转发的呢?这便是接下来的内容。

    转发和重定向

    当然,最原始的方法是像原先的servlet一样使用request和response了,那么只需向我们的方法中传入这两个参数再使用即可。既然我们是用了springmvc的框架,当然有更简单的方法:

    转发

    使用视图解析器

    如上的代码:

    @RequestMapping("/object")
    public String test(User user, Model model){
        //将name的值存入msg中
        model.addAttribute("msg",user.name);
        return "hello";
    }
    

    只需要 return 我们需要转发到的视图即可。那么他是怎么实现的呢?还记得我们配置的springmvc的配置文件吗?对。就是视图解析器的作用。

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

    该视图解析器会自动帮我们完成转发地址的解析

    如上方hello解析完之后便是:/WEB-INF/jsp/hello.jsp

    不使用视图解析器

    当然这是有视图解析器的情况下,当我们将视图解析器注释掉,我们可以这样写:

    @RequestMapping("/object")
    public String test(User user, Model model){
        //将name的值存入msg中
        model.addAttribute("msg",user.name);
        return "/hello.jsp";
    }
    

    或者:

    @RequestMapping("/object")
    public String test(User user, Model model){
        //将name的值存入msg中
        model.addAttribute("msg",user.name);
        return "forward:/hello.jsp";
    }
    

    两者的效果都是一样的

    重定向

    重定不需要使用视图解析器,不过需要注意路径问题:

    @RequestMapping("/object")
    public String test(User user, Model model){
        //将name的值存入msg中
        model.addAttribute("msg",user.name);
        return "redirect:/hello.jsp";
    }
    

    接受数据参数

    RestFul风格

    前边已经提及了参数的一些知识,这里补充一种规范:RestFul风格

    我们接受参数可以这样:

    @RequestMapping("/requestful/{a}/{b}")
    public String test1(@PathVariable int a,@PathVariable int b, Model model){
        int res = a + b;
        model.addAttribute("msg","res is " + res);
        return "hello";
    }
    

    这样发送过来的请求url地址便是

    ip地址/项目名称/requestful/1/2
    

    这样传递参数更加简洁,但是最重要的是更加安全,因为这样其他人根本不知道传递的参数是什么,就算知道了传递什么参数,也不知道该参数对应的键。

    限定请求方式

    @RequestMapping中还有其他参数,其中一个便是method,当我们给这个参数赋值之后,该方法便会只接受该种方式请求的url,如:

    @RequestMapping(value = "/forward",method = RequestMethod.GET)
    public String forwardTest(Model model){
        model.addAttribute("msg","forward");
        return "hello";
    }
    

    那么该方法只会接受get请求。当然实际开发中并不用每次都写上该参数,比较麻烦,每个对应的请求方式都有其对应的注释:

    • @GetMapping()
    • @PostMapping()
    • @DeleteMapping()
    • @PutMapping()

    需要使用哪种就使用哪种即可。

    参数乱码

    如果传递过来的参数中有参数,肯定会遇到乱码问题,别急,我们已经在web.xml中配置好了过滤器,是springmvc帮我们写好的现成的过滤器,可以帮助我们解决乱码的问题。

    <!--spring官方的过滤器-->
        <filter>
            <filter-name>encoding</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>encoding</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    如何只展示数据?

    想起来ajax的异步请求,我们servlet返回json数据了吗?对的,使用response.getWriter().write()方法,如果访问该servlet就会在网页上显示其返回的内容,那么这里我们怎么做到呢?

    只需要在方法上再加一个注释即可:**@ResponseBody **

    这就表明只是作为反映的方法,只返回数据,不做转发或跳转

    那么整个类都是这样的,每个方法上加注释也是很麻烦,这是我们的类可以将@Controller注解换为:**@RestController **,这样就表明该类中的所有方法只做数据的返回了。

    例如:

    package com.annotation.controller;
    
    import com.alibaba.fastjson.JSON;
    import com.annotation.pojo.User;
    import com.google.gson.Gson;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class JsonController {
    
        @RequestMapping("/json1")
        public String test1(){
            User user = new User(1, 5, "小王");
            Gson gson = new Gson();
            String toJson = gson.toJson(user);
            return toJson;
        }
    
        @RequestMapping("/json2")
        public String test2(){
            User user = new User(1, 5, "小王");
            String s = JSON.toJSONString(user);
            return s;
        }
    
    
    }
    

    既然是数据的展示,那么与前端交接,肯定是使用json了,接下来的就是json的部分。

    json

    解决json乱码

    前边的配置文件已经写到了,需要在springmvc的配置文件中进行配置:

    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <constructor-arg value="UTF-8"/>
            </bean>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                        <property name="failOnEmptyBeans" value="false"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    

    记得下jackson的包哦!

    工具的推荐

    • jackson,使用方法网上很多。

      <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
      <dependency>
          <groupId>com.fasterxml.jackson.core</groupId>
          <artifactId>jackson-databind</artifactId>
          <version>2.9.8</version>
      </dependency>
      
    • fastjson,阿里出品

      <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.66</version>
      </dependency>
      
    • gson,一直在使用的一款,谷歌出品

      <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
      <dependency>
          <groupId>com.google.code.gson</groupId>
          <artifactId>gson</artifactId>
          <version>2.8.6</version>
      </dependency>
      

    小结

    springmvc的知识点不是很多,配置也比较少,较spring来说还是比较好理解,目前ssm三个框架已经基本掌握了一点,接下来尝试整合ssm,加油!

  • 相关阅读:
    CODING x 百果园 _ 水果零售龙头迈出 DevOps 体系建设第一步
    Nocalhost 亮相 CD Foundation 国内首届 Meetup,Keith Chan 将出席致辞
    做云原生时代标准化工具,实现高效云上研发工作流
    打造数字化软件工厂 —— 一站式 DevOps 平台全景解读
    WePack —— 助力企业渐进式 DevOps 转型
    CODING Compass —— 打造行云流水般的软件工厂
    Nocalhost —— 让云原生开发回归原始而又简单
    CODING 代码资产安全系列之 —— 构建全链路安全能力,守护代码资产安全
    Nocalhost:云原生开发新体验
    使用 Nocalhost 开发 Kubernetes 中的 APISIX Ingress Controller
  • 原文地址:https://www.cnblogs.com/wuren-best/p/12466363.html
Copyright © 2011-2022 走看看