SpringMVC

SpringMVC

概述

  Spring MVC是Spring提供的一个强大而灵活的web框架。借助于注解,Spring MVC提供了几乎是POJO(普通的java对象)的开发模式,使得控制器的开发和测试更加简单。这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其他bean,通过Spring的依赖注入功能,这些bean被注入到控制器中。

Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。他的两个核心是两个核心:

  处理器映射:选择使用哪个控制器来处理请求

  视图解析器:选择结果应该如何渲染

通过以上两点,Spring MVC保证了如何选择控制处理请求和如何选择视图展现输出之间的松耦合。

 

运行原理

1、Http请求:客户端请求提交到DispatcherServlet。

2、映射处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller。

3、调用处理器:DispatcherServlet将请求提交到Controller。

4、返回ModelAndView:Controller调用业务逻辑处理后,返回ModelAndView。

5、6处理视图映射并返回模型:DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图。

7、Http响应:视图负责将结果显示到客户端。

 上面的架构图是自己画的,有什么不清楚的可以参考下面的图

 

SpringMVC接口解释

(1)DispatcherServlet接口:

Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。

(2)HandlerMapping接口:

能够完成客户请求到Controller映射。

(3)Controller接口:

需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。

Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。

从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。

(4)ViewResolver接口:

Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。

 

DispatcherServlet

是整个Spring MVC的核心。它负责接收HTTP请求组织协调Spring MVC的各个组成部分。其主要工作有以下三项:

(1)截获符合特定格式的URL请求。

(2)初始化DispatcherServlet上下文对应WebApplicationContext,并将其与业务层、持久化层的WebApplicationContext建立关联。

(3)初始化Spring MVC的各个组成组件,并装配到DispatcherServlet中。

 

SpringMVC配置

该项目是一个用户登录的例子,没有连接数据库,和指定的用户名和密码进行比对。

(1)在web.xml中配置分发控制器以及拦截器解决请求参数出现乱码的情况。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  
  <!-- 配置SpringMVC中的分发控制器DispatcherServlet -->
  <servlet>
      <servlet-name>springmvc</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 服务器启动时创建DispatcherServlet对象 -->
        <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet-mapping>
      <servlet-name>springmvc</servlet-name>
      <!-- DispatcherServlet只接收以.do结尾的请求 -->
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  
  <!-- 该拦截器用于解决post请求中请求参数值可能出现乱码的情况 -->
  <filter>
      <filter-name>characterEncoding</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>characterEncoding</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  
  <welcome-file-list>
    <welcome-file>/login/index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

(2)jsp页面

index.jsp

<body>
      ${error }
      <form action="<%=path %>/user/login.do" method="post">
          用户名:<input type="text" name="username"><br>
          密码:<input type="password" name="userpass"><br>
          <input type="submit" value="登录">
      </form>
</body>

success.jsp

<body>
     欢迎,${uN }<br>
</body>

 

(3)编写控制器

UserController.java

package com.ghq.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

//指定当前类是处理器,不需要实现任何接口, @Controller是Spring的注解
@Controller
//指定了处理器url前缀   @RequestMapping是SpringMVC的注解
@RequestMapping("/user")
public class UserController{
    //指定了处理器url后缀,当访问<%=path%>/user/login.do时,请求的是login方法
    @RequestMapping("/login")
    //@RequestParam指出该方法的参数接收请求参数的值
    public ModelAndView login(@RequestParam String username,String userpass) throws Exception {
        ModelAndView mv = new ModelAndView();
        if ("张三".equals(username) && "zs".equals(userpass)) {
            //存放普通数据
            mv.addObject("uN", username);
            //存放与响应有关的标志
            mv.setViewName("success");
            return mv;
        } else{
            mv.addObject("error", "你的用户名或密码有误");
            mv.setViewName("index");
            return mv;
        }
        
    }
}

 

Controller中方法的返回一般为String或ModelAndView

  ModelAndView通过setViewName方法跳转到指定的页面。

  String根据String字符串返回对应的地址prefix前缀+返回值+suffix后缀组成。

 

(4)编写SpringMVC配置文件

springmvc-servlet.xml(该文件名前半部分的springmvc和web.xml中配置的servlet-name的名字相同)

<?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
  ">
  
  <!-- 让Spring识别注解 -->
  <context:component-scan base-package="com.ghq.controller"></context:component-scan>
  <!-- 让SpringMVC识别注解 -->
  <mvc:annotation-driven></mvc:annotation-driven>
  
  <!-- 配置视图解析器 -->
  <bean id="resourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
      <!-- 指出目标视图的前缀 -->
      <property name="prefix" value="/login/"/>
      <!-- 指出目标视图的后缀 -->
      <property name="suffix" value=".jsp"/>
  </bean>
    
</beans>

 

注解

@Controller

@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是SpringMVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式:

(1)在SpringMVC 的配置文件中定义MyController 的bean 对象。

(2)在SpringMVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。

<!--方式一-->
<bean class=" com.ghq.controller.UserController.java"/>
<!--方式二-->
<context:component-scan base-package="com.ghq.controller"/> //路径写到controller的上一层

 

@RequestMapping

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

默认属性为value,可以省略。即指定请求的地址。

@RequestParam

只要处理器中形参列表的名字和请求参数同名,形参就可以封装同名的请求参数值,可以完成类型的自动转换,所以形参列表中可以不添加@RequestParam注解。

如果处理器的方法中需要封装请求参数的形参很多,而且这些形参都是某个类的属性的化,建议使用类做为形参。

SpringMVC中的转发与重定向

Spring MVC的处理器的方法默认使用的是转发而不是重定向,要使用显式的转发,应该让该方法返回String类型,并且返回”forward:/目录/jsp页面”或者是返回“forward:/前缀/请求到方法的映射.do”, Spring MVC中转发的特点和jspServlet中转发的特点一样。

重定向的使用方法和转发一样,只需将关键字forward改成redirect。

参考博客

[1]Spring MVC原理及配置详解

http://www.07net01.com/2016/04/1483383.html

[2] springmvc常用注解标签详解

http://www.cnblogs.com/leskang/p/5445698.html

 

原文地址:https://www.cnblogs.com/ghq120/p/8342316.html