SpringMVC

SpringMVC

开发服务器端程序。一般基于两种形式。一种是C/S架构,一种是B/S架构,使用java语言基本是采用B/S架构的程序,B/S架构又分为三层架构。

三层架构:

  1. 表现层:WEB层,采用和客户端进行交互,表层一般会采用MVC的设计模式。
  2. 业务层:处理公司具体的业务逻辑
  3. 持久层:用来操作数据库。

MVC模型:

MVC全名是Model View Controller 模型视图控制器。

Model:数据模型,JavaBean的类,用来进行数据的封装。

View:指JSP,HTML用来展示数据给用户。

Controller;用来接受用户的请求,整个流程的控制器,用来进行数据校验等。

SpringMVC的优势

1.清晰的角色划分:
 前端控制器(DispatcherServlet)
 请求到处理器映射(HandlerMapping)
 处理器适配器(HandlerAdapter)
 视图解析器 (ViewResolver)
 处理器或页面控制器 (Controller)
 验证器 ( Validator) 
 命令对象 (Command  请求参数绑定到的对象就叫命令对象)
 表单对象 (Form Object 提供给表单展示和提交到的对象就叫表单对象)。
 2、分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要。  
 3、由于命令对象就是一个 POJO,无需继承框架特定 API,可以使用命令对象直接作为业务对象。
 4、和 Spring 其他框架无缝集成,是其它 Web 框架所不具备的。  
 5、可适配,通过 HandlerAdapter 可以支持任意的类作为处理器。 
 6、可定制性,HandlerMapping、ViewResolver 等能够非常简单的定制。  
 7、功能强大的数据验证、格式化、绑定机制。  
 8、利用 Spring 提供的 Mock 对象能够非常简单的进行 Web 层单元测试。  
  9、本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。 10、强大的 JSP 标签库, 

    使用JSP 编写更容易。 ………………还有比如RESTful风格的支持、简单的文件上传、约定大于配置的契约式编程支持、基于注解的零配 置支持等等。  

创建SpringMVC的maven项目

在pom.xml中添加依赖

<properties> 

     <project.build.sourceEncoding>UTF-</project.build.sourceEncoding> 

      <maven.compiler.source>1.8</maven.compiler.source> 

      <maven.compiler.target>1.8</maven.compiler.target> 

     <!--锁定spring的版本--> 

      <spring.version>5.0.2.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-web</artifactId> 

       <version>${spring.version}</version> 

      </dependency> 
 <dependency> 

       <groupId>org.springframework</groupId> 

        <artifactId>spring-webmvc</artifactId> 

       <version>${spring.version}</version> 
 </dependency> 

      <dependency> 

        <groupId>javax.servlet</groupId> 

        <artifactId>servlet-api</artifactId> 

        <version>2.5</version> 

        <scope>provided</scope> 

      </dependency> 

      <dependency> 

       <groupId>javax.servlet.jsp</groupId> 

       <artifactId>jsp-api</artifactId> 

        <version>2.0</version> 

       <scope>provided</scope> 

      </dependency> 

   </dependencies> 

在工程的web.xml中配置核心SpringMVC的核心控制器DispatcherServlet

 <web-app xmlns:xsi "http://www .w3.org/2001/XMLSchema-instance" 

         xmlns "http://java.sun.com/xml/ns/javaee" 

          xsi:schemaLocation "http://java.sun.com/xml/ns/javaee  

    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 

         id "WebApp_ID" version "2.5"> 

       <!--配置springMVC的核心控制器--> 

     <servlet> 

         <servlet-name>dispatcherServlet</servlet-name> 

   <servlet-
   class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 

     </servlet> 

      <servlet-mapping> 

         <servlet-name>dispatcherServlet</servlet-name> 
			 <url-pattern>/</url-pattern> 

     </servlet-mapping> 

  </web-app> 

在resources目录下创建springmvc.xml配置文件

 <?xml version "1.0" encoding "UTF-8" ?> 
  <beans xmlns "http://www .springframework.org/schema/beans" 
 xmlns:mvc "http://www .springframework.org/schema/mvc" 
        xmlns:context "http://www .springframework.org/schema/context" 
       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 
  http://www .springframework.org/schema/mvc 
 http://www .springframework.org/schema/mvc/spring-mvc.xsd 
  http://www .springframework.org/schema/context 
 http://www .springframework.org/schema/context/spring-context.xsd"> 
    <!--开启组件的注解扫描--> 
    <context:component-scan base-package "org.westos"></context:component- scan> 
 </beans> 

在web.xml中添加配置,加载springmvc.xml配置文件

  <!--配置springMVC的核心控制器--> 
        <servlet> 
            <servlet-name>dispatcherServlet</servlet-name> 
         <servlet- 
class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 

         <!--加载springmvc.xml配置文件--> 
           <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>classpath:springmvc.xml</param-value> 
          </init-param> 
           <!--服务器一开启就创建DispatcherServlet对象--> 
         <load-on-startup>0</load-on-startup> 
     </servlet> 
      <servlet-mapping> 
          <servlet-name>dispatcherServlet</servlet-name> 
        <url-pattern>/</url-pattern> 
  			 </servlet-mapping>

创建处理请求的类

 @Controller  //采用注解的方式把这个类交由Spring容器管理 
    public class Hello { 
 @RequestMapping(value   "/hello") //配置请求的映射路径 
   public String hello(){ 
   System.out.println("请求来了"); 
     return "success";  //返回跳转到jsp页面的名称 
       } 
    } 

提供一个hello()方法这个方法就是用来处理请求的,以及返回视图页面名称,进行跳转,在hello()方法上添加的@RequestMapping注解,可以用来配置请求路径。

在springmvc.xml配置文件中配置视图解析器 InternalResourceViewResolver ,以及开启 spirngmvc的注解驱动

<!--配置视图解析器--> 

    <bean class "org.springframework.web.servlet.view .InternalResourceViewResolver"  id "viewResolver"> 

 <!--prefix 前缀  suffix 后缀 拼完成就是 /WEB-INF/success.jsp 因为我们返回 
的是一个success这个字符,然后再拼接上我们配置的前缀和后缀,就可以跳转到success.jsp这个页面--> 

        <property name "prefix" value "/WEB-INF/"></property> 
       <property name "suffix" value ".jsp"></property> 
         </bean> 
     <!--开启springmvc的注解驱动--> 
    <mvc:annotation-driven></mvc:annotation-driven> 

在WEB-INF目录下创建success.jsp页面

因为我们在hello()方法中返回的名称叫做success 所以这个jsp页面就叫做success.jsp 
 这个success.jsp要放在WEB-INF目录下,因为我们在配置视图解析器的时候,前缀配置的就是/WEB-INF/ 
就是这行<property name "prefix" value "/WEB-INF/"></property> 

在index.jsp中请求hello这个方法

<a href "${pageContext.request.contextPath}/hello">请求后台</a> 

发布项目,进行测试

对这个案例的请求进行分析:

当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,就会加载springmvc配置文件

开启了注解扫苗,那么HelloController对象就会被创建

从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解,找到执行的具体方法。

根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件。

Tomcat服务器渲染页面做出响应。

SpringMVC的详细执行流程
  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器
  3. HandlerMapping处理器映射器根据请求url找到具体的处理器(也就是所说的Controller),生成处理器对象及处理器拦截器一并返回给DispatcherServlet。
  4. DispatcherServlet通过HandlerAdapt处理器适配器调用处理器。
  5. 执行处理器(controller 也叫后端控制器,就是自己编写的controller)
  6. Controller执行完成返回给ModelAndView
  7. HandlerAdapt将ModelAndView执行结果返回给DiapatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ViewResolver解析后返回具体View
  10. DispacherServlet将View进行渲染视图(也就是将模型数据填充至视图中)。
  11. DispatcherServlet响应用户。
组件分析
1.DispatcherServlet:前端控制器 
 用户的请求到达前端控制器,相当于mvc模式中的c。spatcherServlet是整个流程控制的 
中心,相当于是SpringMVC的大脑,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2.HandlerMapping:处理器映射器 
 HandlerMapping负责根据用户请求url找到Handler处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 
 3.Handler:处理器 
  Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。 由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。这里所说的Handler就是我们自己编写的Controller 。
  4.HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。  
  5.ViewResolver:视图解析器 
   View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 
   6.View:视图 
springmvc框架提供了很多的View视图类型的支持,包括:jstlView,freemarkerView, pdfView等。我们最常用的视图就是jsp。 
 一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。 
 在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。 
 需要用户开发的组件有handler、view 
  使 用 <mvc:annotation-driven>  自 动 加 载 RequestMappingHandlerMapping  (处理映射器) 和 RequestMappingHandlerAdapter  (处理适配器可 用 在 SpringMVC.xml 配置文件中使用 <mvc:annotation-driven>替代注解处理器和适配器的配置。它就相当于在 xml 中配置了:  
RequestMapping注解 属性的介绍
  1. 注解的作用:是建立请求URL和处理方法之间的对应关系

  2. RequestMapping注解可以作用在方法和类上

    作用在类上:第一级的访问目录

    作用在方法上:第二级的访问目录。

    @RequestMapping(path  = "/demo") //一级路径 
      public class Hello { 
          @RequestMapping(value =  "/hello",params  {"username zhangsan"} ) //二级路径 
         public String hello() { 
           System.out.println("请求来了"); 
          return "success"; 
         } 
     } 
      上面组合起来的路径就是 /demo/hello 那么前台请求路径也要跟着变 
    <a href "${pageContext.request.contextPath}/demo/hello">请求后台</a> 
    ${ pageContext.request.contextPath}动态获取上下文路径 
     path 配置请求路径 
     value 配置请求路径
     value属性和path属性意思是一样的,用哪个都可以 
    
    mthod 配置介绍那种请求方式 
    例如:@RequestMapping(value   "/hello",method  
    {RequestMethod.GET ,RequestMethod.POST}) 意思是接收get请求和post请求  
    params  指定限制请求参数的条件
     例如:  @RequestMapping(value =  "/hello",params  {"username"} ) 表示请求的 
          时候必须有请求参数username 当但是跟请求参数的值没关系 
    <a href = "${pageContext.request.contextPath}/hello?username = zhangsan">请求后台</a> 
     如果配置了请求参数的名称和值,那么在请求时,必须保持一致 
    @RequestMapping(value =  "/hello",params  {"username = zhangsan"} ) 
     <a href = "${pageContext.request.contextPath}/hello?username = zhangsan">请求后台</a> 
    请求时的参数名和值要和 @RequestMapping注解中配置的一致 
    headers 发送的请求中必须包含的请求头 
     例如:@RequestMapping(value  = "/hello",headers =  "cookie") 请求信息中必须包含cookie这个请求头 
      @RequestMapping(value =  "/hello2",method  = {RequestMethod.GET}) 
    上面的写法可以使用一个注解来代替:@GetMapping(value= "/hello2") 
    @RequestMapping(value =  "/hello3",method = {RequestMethod.POST}) 
     上面的写法可以使用一个注解来代替:@PostMapping(value =  "/hello3") 
    

    请求参数的绑定

    请求参数的绑定说明

    绑定机制:

    1. 表单提交的数据都是k=v的格式 username=cherry&password=123456;
    2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的。
    3. 提交表单的name和参数的名称是相同的。

    支持的数据类型:

    1. 基本数据类型和字符串类型
    2. 实体类型(JavaBean)
    3. 集合数据类型(List,map集合等)

    基本数据类型和字符串类型

    1. 提交表单的name和参数的名称是相同的
    2. 区分大小写的

    实体类型(JavaBean)

    1. 提交表单的name和javaBean中的属性名称需要一致
    2. 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象,属性。例如:address.name

    给集合属性封装数据

    1. JSP页面的编写方式:list[0].属性

    超链接请求后台携带请求参数

jsp页面中 
<a href "${pageContext.request.contextPath}/param/get? 
      username zhangsan&password 123456">请求后台携带参数</a> 
  2. 后台要求处理前台1.请求的方法的形参名称和请求参数的名称保持一致,即可接收到请求参数的值 
   @Controller 
    @RequestMapping("/param") 
    public class ParamDemo { 
     @RequestMapping("/get") 
  public String getParam(String username,String password){
   System.out.println(username);
     System.out.println(password);
      return "success"; }
      }
  1. 将请参数封装到JavaBean中

    1. 如果前台是个表单请求后台,表单中的数据较多,可以使用一个实体类,将表单提交的数据封装到实体类中

      <form action "${pageContext.request.contextPath}/param/getform"  
          method "post"> 
      	 姓名:<input type "text" name "username" /><br /> 
           密码:<input type "text" name "password" /><br /> 
           金额:<input type "text" name "money" /><br /> 
           <input type "submit" value "提交" /> 
        </form> 
      
      

      2.提供一个javaBean对象,用来封装表单中的数据,要求JavaBean的属性名和表单中name属性值保持一致即可。

      public class Account implements Serializable { 
       private String username; //属性名和表单中name属性值保持一致 
       private String password; 
       private Double money; 
         // get set 方法略... 
         } 
      

      3.后台处理表单请求的方法形参,是一个JavaBean类型即可

      @Controller 
      @RequestMapping("/param") 
       public class ParamDemo { 
         @RequestMapping("/getform") 
         public String getParam(Account account){ 
             System.out.println(account); 
            return "success"; 
          } 
       } 
      

      4.如果JavaBean的中的属性有一个属性是另一个对象,如何封装

      例如:JavaBean中的属性中有一个User类型的
       public class Account implements Serializable { 
          private String username; 
          private String password; 
          private Double money;   
          private User user; //维护着另一个JavaBean的引用 
           //get set 方法略... 
         } 
       public class User { 
        private String uname; 
        private Integer age; 
           //get set 方法略 
        } 
        
        JSP页面中表单的写法
      <form action "${pageContext.request.contextPath}/param/getform"  
          method "post"> 
         姓名:<input type ="text" name= "username" /><br /> 
         密码:<input type ="text" name= "password" /><br /> 
         金额:<input type= "text" name ="money" /><br /> 
        <%--这里user是Account类中的属性名 
          uname和age是User类中的属性名     --%> 
       用户姓名:<input type ="text" name ="user.uname" /><br /> 
       用户年龄:<input type="text" name= "user.age" /><br /> 
        <input type ="submit" value="提交" /> 
        </form> 
        处理表单请求的方法的形参还是Account类型即可 
        @Controller 
       @RequestMapping("/param") 
       public class ParamDemo { 
        @RequestMapping("/getform") 
         public String getParam(Account account){ 
             System.out.println(account); 
           return "success"; 
           } 
        } 
      解决表单提交数据是post请求方式时,中文会乱码的情况 
      当表单提交方式是get请求时中文不会乱码,但是是post请求的时候会中文乱码。可以在web.xml中配置一个SoringMVC提供的一个过滤器CharacterEncodingFilter 
      配置如下:
      <filter> 
       <filter-name>encodingFilter</filter-name> 
       <filter- 
      class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
       <!--指定字符集 encoding这个属性可以在CharacterEncodingFilter类中找到--> 
       
            <init-param> 
            <param-name>encoding</param-name> 
             <param-value>UTF-8</param-value> 
           </init-param> 
         </filter> 
         
         <filter-mapping> 
         <filter-name>encodingFilter</filter-name> 
           <url-pattern>/*</url-pattern> 
         </filter-mapping> 
      

      5.如果JavaBean中的属性是一个List类型或Map类型,如何封装请求参数

      1. JavaBean中属性的类型是List类型或Map类型,封装请求参数的方法。
      public class Account implements Serializable { 
          private String username; 
          private String password; 
          private Double money; 
          private List<User> list;//集合里面装的是User类型 
          private Map<String,User> map; //键是String类型,值时User类型 
       //get set 方法略... 
         } 
      
      

      2.前台页面的写法:

       <form action "${pageContext.request.contextPath}/param/getform" 
          method "post"> 
      姓名:<input type ="text" name= "username" /><br /> 
      密码:<input type ="text" name= "password" /><br /> 
      
      金额:<input type= "text" name ="money" /><br /> 
        <%--list是Account类中的属性名 而[0]是索引--%> 
      
      用户姓名:<input type ="text" name= "list[0].uname" /><br /> 
      
      用户年龄:<input type ="text" name ="list[0].age" /><br />     
      <%--map是Account类中的属性名  而['one'] one是自己指定一个键名--%> 
      
       用户姓名:<input type ="text" name ="map['one'].uname" /><br /> 
       用户年龄:<input type= "text" name ="map['one'].age" /><br /> 
           <input type ="submit" value ="提交" /> 
        </form> 
      

      3.后台处前台请求的方法形参还是一个Account类型

      @Controller 
      @RequestMapping("/param") 
      public class ParamDemo { 
       @RequestMapping("/getform") 
       public String getParam(Account account){ 
            System.out.println(account); 
            return "success"; 
          } 
       } 
      
      

      6.如果JavaBean中的一个属性是Date日期类型,如何封装

      1. 如果一个JavaBean中有一个属性是Date类型,那么前台提交时他写的日期字符串格式是 2019/08/01 也就是用 /分割那么SpringMVC是可以把日期字符串转换成日类型,但是如果我们不用/ 分割想要自己定义日期字符串的格式,那么就需要使用一个转换器来进行转换

      2. 提供一个Java类 提供一个日期类型的属性

        public class User { 
           private String uname; 
           private Integer age; 
           private Date birthday; //日期类型的属性 
            //get set 方法省略... 
             } 
        
      3. 前台页面

        <form action
        "${pageContext.request.contextPath}/param/getform" method ="post"> 
        用户姓名:<input type= "text" name ="uname" /><br /> 
           用户年龄:<input type= "text" name ="age" /><br /> 
             用户生日:<input type= "text" name ="birthday" /><br /> 
           <input type= "submit" value="提交" /> 
          </form> 
        
      4. 后台处理请求的方法

         @Controller 
         @RequestMapping("/param") 
         public class ParamDemo { 
          @RequestMapping("/getform") 
           public String getParam(User user){ 
                 System.out.println(user); 
               return "success"; 
            } 
          } 
        
      5. .如果前台页面生日的表单填写 2017/03/05 这种个格式,是能自动封装进JavaBean中的

      6. 如果是自己要指定格式,那么首先我们自己定义一个类,实现一个SpringMVC的转换器接口

  Converter 
     public class MyDateConverter implements Converter<String,Date> { 
        @Override 
     public Date convert(String dateStr){ 
         Date date null; 
          if(dateStr! null){ 
         try { 

 date  new SimpleDateFormat("yyyy-MM-dd").parse(dateStr); 
               } catch (ParseException e) { 
                  e.printStackTrace(); 
                } 
           }else{ 
              throw new RuntimeException("日期字符串为空"); 
            } 
       return date; 
       } 
    }

​ 7. 注册自定义类型转换器,在springmvc.xml配置文件中编写配置

 <!--注册我们的自定义日期转换器--> 
   <bean class ="org.springframework.context.support.ConversionServiceFactoryBean"  id ="conversionServiceFactoryBean"> 
     <property name ="converters"> 
      <set> 
   <bean class="org.westos.domain.MyDateConverter"></bean> 
           </set> 
     </property> 
  </bean> 
  1. 记得在开启Spring对MVC注解的支持的配置中加上ConversionServiceFactoryBean对象
 <!--开启springmvc的注解驱动--> 
  <mvc:annotation-driven conversion-
       service ="conversionServiceFactoryBean"></mvc:annotation-driven> 

在控制器中使用原生的Servlet API对象

只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象

@RequestMapping("/demo") 
  public String getServletAPI(HttpServletRequest request,  
       HttpServletResponse response){ 
     System.out.println(request); 
         HttpSession session =  request.getSession(); 
           ServletContext servletContext =  session.getServletContext(); 
     System.out.println(response); 
       return "success"; 
     } 

SpringMVC的常用注解

1.RequestParam注解

作用:把请求中的指定名称的参数传递给控制器中的形参赋值,此注解用在形参上。

属性

​ 1. value:请求参数中的名称 或者使用name属性 两个一样

​ 2. required:请求参数中是否必须提供此参数,默认值是true,必须提供

,但是如果我们请求的参数名就是和方法的形参名不保持一致可以使用 RequestParam注解 来解决

前台请求参数名是 uname

 <a href "${pageContext.request.contextPath}/anno/testRequestParam? 
       uname= zhangsan">请求后台</a> 

后台示例如下:

 @Controller 
   @RequestMapping("/anno") 
  public class AnnotationDemo { 
        @RequestMapping("/testRequestParam") 
public String testRequestParam(@RequestParam(value =  "uname") String username){ 
    System.out.println(username); 
       return "success"; 
      } 
    } 
    required属性默认是true 也就是说 请求连接中参数必须要有一个uname, 名字不对,或没有请求参数都不行。

2.RequestBody注解

作用:用于获取请求体的内容 (注意:get方法不可以,因为get请求没有请求体),此注解用在方法的形参上

属性 :

  1. required:是否必须有请求体,默认值是true
前台代码 post请求 
 <form action "${pageContext.request.contextPath}/anno/testRequestBody"  
       method="post"> 
  用户姓名:<input type="text" name="uname" /><br /> 
 用户年龄:<input type="text" name="age" /><br/> 
 <input type="submit" value="提交" /> 
 </form> 

后台获取请求体内容

 @Controller 
    @RequestMapping("/anno") 
    public class AnnotationDemo { 
    @RequestMapping("/testRequestBody") 
    public String testRequestBody(@RequestBody String body){ 
     System.out.println(body); 
       return "success"; 
     } 
     }

输出的请求体内容是 uname = zhangsan & age = 123456;

用@RequestBody这个注解,获取请求参数,是针对如果前台用的是Ajax请求,那么会向后台提交的是JSON字符串,所以我们就得通过@RequestBody 来获取到JSON字符串,然后解析JSON字符串

PathVariable注解

作用:拥有绑定url中的占位符的。例如:url中有/delete/{id},{id}就是占位符

属性: value:指定url中的占位符名称

Restful风格的URL

请求路径一样,可以根据不同的请求方式去执行后台的不同方法

restful风格的URL优点

  1. 结构清晰
  2. 符合标准
  3. 易于理解
  4. 扩展方便

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

资源:互联网所有的事物都可以被抽象为资源

资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。

分别对应 添加、 删除、修改、查询。

 传统方式操作资源 

  http://127.0.0.1/item/queryItem?id 1    查询,GET 

  http://127.0.0.1/item/saveItem          新增,POST 

  http://127.0.0.1/item/updateItem        更新,POST 

  http://127.0.0.1/item/deleteItem?id 1   删除,GET或POST 

PathVariable注解

传统方式前台页面有个get请求,且携带有请求参数 uid 1

<a href "${pageContext.request.contextPath}/anno/testPathVariable?uid =1">请求后台</a> 

后台获取uid的值

@Controller 
  @RequestMapping("/anno") 
   public class AnnotationDemo { 
   @RequestMapping("/testPathVariable") 
public String testPathVariable(String uid){//形参名和请求参数名保持一致 
       System.out.println(uid); 
 return "success"; 
 }
 }

采用Restful风格的请求URL如下

<a href "${pageContext.request.contextPath}/anno/testPathVariable/1">请求后台</a> 

后台需要使用@PathVariable这个注解来拿到 1 这个值,并设置给形参

@Controller 
 @RequestMapping("/anno") 
 public class AnnotationDemo { 
@RequestMapping("/testPathVariable/{uid}") //{uid}请求参数占位符 
 //value "uid" 中的uid跟占位符uid名称保持一致,就会取出请求URL中的1设置给形参uid 
 public String testPathVariable(@PathVariable(value =  "uid") String uid){ 
 System.out.println(uid); 
 return "success"; 
 } 
  } 

然如果方法形参的名称和{uid}占位符的名称一样,那么@PathVariable的value属性值可以不写

 @Controller 
  @RequestMapping("/anno") 
  public class AnnotationDemo { 
    @RequestMapping("/testPathVariable/{uid}") //{uid}请求参数占位符 
   //如果形参的名称和占位符的名称一样,可以省略@PathVariable注解的value属性 
   public String testPathVariable(@PathVariable String uid){ 
       System.out.println(uid); 
       return "success"; 
    } 
}

响应视图和环境搭建

响应数据和结果视图
  1. 返回一个字符串

    前台代码
    <a href="${pageContext.request.contextPath}/user/hello">请求后台</a>
    后台代码:
      @Controller
    @RequestMapping(value = "/user")
    public class UserController {
        @RequestMapping("/hello")
        public String hello(Model model){
            //模拟从数据库中查询出了一个Use对象
            User user = new User();
            user.setUname("张三");
            user.setAge(23);
            //把user对象存储到请求域中,转发到success.jsp页面后,取出域中的数据
            model.addAttribute("user",user);
    
            return "success"; //返回要跳转的jsp页面的名称
        }
    }
    success.jsp 页面取出请求域中的数据
     <body>
    	<h1>成功跳转</h1>
    	<h3>${user.uname}</h3>
    	<h3>${user.age}</h3>
    </body>
    
  2. 返回void

    如果控制器的方法返回值编写成void,执行程序报404的异常,默认查找JSP页面没有找到。 
        如果返回void那么进行页面的跳转,就需要我们用原生的Servlet API 进行跳转。跳转路径需要我们自己编写,因为使用原生的Sevlet API 不会执行视图解析器
        .前台代码:
         <a href="${pageContext.request.contextPath}/user/testVoid">请求后台</a>
       
      后台代码
      @Controller
    @RequestMapping(value = "/user")
    public class UserController {
        @RequestMapping("/testVoid")
        public void testVoid(HttpServletRequest request, HttpServletResponse response) throws Exception {
            System.out.println("收到请求");
            //使用原生的Servlet API 进行页面跳转
          request.getRequestDispatcher("/WEB-INF/success.jsp").forward(request,response);
            //或者重定向,注意重定向不能访问到WEB-INF下的资源
           // response.sendRedirect(request.getContextPath()+"/index.jsp");
        }
    }
    
  3. 返回值是ModelAndView对象

    ModelAndView对象是SpringMVC提供的一个对象,可以用来调整具体的JSP视图
     使用ModelAndView可以把数据存到请求域中,还可以指定要跳转的视图
     前台代码:
        <a href="${pageContext.request.contextPath}/user/testMV">请求后台</a>
        后台代码
        @Controller
    @RequestMapping(value = "/user")
    public class UserController {
        @RequestMapping("/testMV")
        public ModelAndView testVoid() throws Exception {
            System.out.println("收到请求");
            ModelAndView mv = new ModelAndView();//创建对象
            //模拟查询出的用户
            User user = new User();
            user.setUname("张三");
            user.setAge(23);
            //把user对象存到请求域中
            mv.addObject("user",user);
            //设置要跳转的视图
            mv.setViewName("success");
            //返回mv
            return mv;
        }
    }
    
  4. 跳转页面的另一种方式forward(转发)和redirect(重定向)

    forward(转发)和redirect(重定向)是spring提供的两个关键字,可以进行页面的跳转
    或者可以进行Controller间方法的跳转
    前台代码:
     <a href="${pageContext.request.contextPath}/user/testForwardAndRedirect">请求后台</a>
     后台代码
     @Controller
    @RequestMapping(value = "/user")
    public class UserController {
        @RequestMapping(value = "/testForwardAndRedirect")
        public String testForwardAndRedirect(){
            System.out.println("收到请求");
    
            //转发:forward: 这个是固定写法,路径要写正确了,因为不走视图解析器
            return "forward:/WEB-INF/success.jsp";
    
    
            //重定向: redirect: 固定写法 可以不用写项目路径,重定向不能访问WEB-INF目录下的资源
            //return "redirect:/index.jsp";
        }
     }   
    
    
  5. 配置静态资源不进行拦截

    下面我们要在jsp页面中使用Jquery来进行一个异步请求,向后台发送json数据
    我们在项目的webapp目录下新建一个 js 文件夹,专门用来放一些 xxx.js文件
    我们把Jquery的库文件jquery.min.js放到此目录下
    然后在index.jsp页面引入jquery.min.js
    编写前台代码,我们给按钮绑定一个点击事件,然后点击按钮,弹出一个框
    <html>
    <head>
        <title>Title</title>
        <script src="js/jquery.min.js"></script>
        <script>
            $(function () {
                $('#btn').click(function () {
                    alert("hello");
                });
            });
        </script>
    </head>
    <body>
        <h1>入门案例</h1>
        <button id="btn">发送ajax请求</button>
    </body>
    </html>
    但是当我们点击按钮时,发现弹框并没有,我们的代码没有写错,原因是我们放在服务器端的这些静态
    资源文件被SpringMVC的前端控制器拦截了,我们无法请求到jquery.min.js这个静态资源。
    我们配置的 <url-pattern>/</url-pattern> 这行中  / 斜杠表示拦截所有,那么静态资源就会被拦截
    所以我们需要在 springMVC.xml中配置哪些静态资源不被拦截
    DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到,从而 不能被使用。解决问题就是需要配置静态资源不进行拦截,在springmvc.xml配置文件添加如下配置 
    *** mvc:resources标签配置不过滤 
    	1. location元素表示webapp目录下的包下的所有文件 
    	2. mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b
    	
    设置如下:	
    	 <!-- 设置静态资源不过滤 -->   
         <!-- 样式 -->  
    	 <mvc:resources location="/css/" mapping="/css/**"/>   
          <!-- 图片 -->  
    	 <mvc:resources location="/images/" mapping="/images/**"/>   
    	 <!-- javascript -->
    	 <mvc:resources location="/js/" mapping="/js/**"/>  
    	如果你的DispatcherServlet拦截 *.do 或 *.action这样的URL,就不存在访问不到静态资源的问题。
    如果你的DispatcherServlet拦截“/”,拦截了所有的请求,同时对 *.js,*.jpg *.css 的访问也就被拦截了。 
    

配置静态资源不被拦截的方式2:

 方式2:配置静态资源不被拦截
  <mvc:default-servlet-handler/>

配置好不拦截静态资源后,我们使用ajax进行请求后台,给后台发送ajax数据,后台收到json数据后,进行解析,把数据封装到JavaBean中

http://jquery.cuishifeng.cn/ jquery在线中文文档

编写前台代码
$(function () {
            $('#btn').click(function () {
                //alert("hello");
                $.ajax({
                    url: "${pageContext.request.contextPath}/user/testAjax", //请求后台路径
                    type: "post", //请求方式
                    contentType: "application/json;charset=UTF-8", //发送信息至服务器时内容编码类型
                    //给后台发送json数据,注意json语法,最外面用''单引号引起来,里面的键值用双引号引起来,而且json用紧凑格式
                    data: '{"uname":"张三","age":100}',
                    dataType: "json",//预期服务器返回的数据类型。我们让服务器返回json格式
                    success: function (data) { //服务器成功响应后的,回调函数
                        alert(data);
                    }
                });
            });
        });

后台收到请求后,可以先取出请求体数据打印看一下 要使用我们之前学习过的一个注解 @RequestBody 可以获取请求体的数据

请求到数据之后先进行数据打印测试,看数据是否正确。
@Controller
@RequestMapping(value = "/user")
public class UserController {
    @RequestMapping("/testAjax")
    public String testAjax(@RequestBody String body) throws Exception {
        System.out.println("收到请求");
        System.out.println(body);
        return "success";
    }
}

使用@RequestBody注解把json的字符串转换成JavaBean的对象
1.我们在获取到了请求体的数据后,其实就是个字符串,所以我们需要把json字符串解析封装到JavaBean里面去
这个解析json字符串封装进JavaBean的操作,那么我可以使用一组jar包来帮我们完成,并且我们收到请求后
把从数据查询出的数据,以JSON的形式返回给前台
2.我们修改一下方法的形参类型和返回值类为User类型
@Controller
@RequestMapping(value = "/user")
public class UserController {
    @RequestMapping("/testAjax")
    public User testAjax(@RequestBody User user) throws Exception {
        System.out.println("收到请求");
        System.out.println(user);
        
        //模拟从数据库中查询出的数据
        User user1 = new User();
        user1.setUname("张曼玉");
        user1.setAge(18);
        return user1;
    }
}
那么解析前台发来的json数据封装到User中,我们只需要引入下面jar包,则自动会帮我们完成
	 json字符串和JavaBean对象互相转换的过程中,需要使用jackson的jar包
 
 	在pom.xml中添加下面的jar包坐标
 	
	<dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>
    5.我们把从数据库查询出的User对象,再转换成JSON字符串响应给前台,只需要在返回值前面加上一个注解@ResponseBody 即可jackson的jar包就会把user1这个对象转换成json给前台响应回去


@Controller
@RequestMapping(value = "/user")
public class UserController {
    @RequestMapping("/testAjax")
    @ResponseBody
    public User testAjax(@RequestBody User user) throws Exception {
        System.out.println("收到请求");
        System.out.println(user);

        //模拟从数据库中查询出的数据
        User user1 = new User();
        user1.setUname("张曼玉");
        user1.setAge(18);
        return user1;
    }
}
6.前台在success回调函数中解析JSON对象,展示即可
<script>
        $(function () {
            $('#btn').click(function () {
                //alert("hello");
                $.ajax({
                    url: "${pageContext.request.contextPath}/user/testAjax", //请求后台路径
                    type: "post", //请求方式
                    contentType: "application/json;charset=UTF-8", //发送信息至服务器时内容编码类型
                    //给后台发送json数据,注意json语法,最外面用''单引号引起来,里面的键值用双引号引起来,而且json用紧凑格式
                    data: '{"uname":"aa","age":100}',
                    dataType: "json",//预期服务器返回的数据类型。我们让服务器返回json格式
                    success: function (data) { //服务器成功响应后的,回调函数 data就是后台返给前台的json数据
                        alert(data);
                        alert(data.uname);
                        alert(data.age);
                    }
                });
            });
        });
    </script>
注解解释

@ResponseBody

  1. 用于前后台异步交互
  2. 可以使用在类上或者方法上
  3. 使用在类上表示该类中左右方法都返回JSON数据。
  4. 使用在方法上,表示该方法返回JSON数据。

@RestController

 这个注解综合了@ResponseBody和@Controller
  @RestController 注解代码如下:


@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
    @AliasFor(
        annotation = Controller.class
    )
    String value() default "";
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值