Java Web系列:Spring MVC 基礎

jopen 8年前發布 | 47K 次閱讀 MVC模式 Spring MVC Web框架

1.Web MVC基礎

MVC的本質是表現層模式,我們以視圖模型為中心,將視圖和控制器分離出來。就如同分層模式一樣,我們以業務邏輯為中心,把表現層和數據訪問層代碼分離出來是一樣的方法。框架只能在技術層面上給我們幫助,無法在思考和過程上幫助我們,而我們很多人都不喜歡思考和嘗試。

Java Web系列:Spring MVC 基礎

2.實現Web MVC的基礎

實現Web MVC基礎可以概括為1個前段控制器和2個映射。

(1)前端控制器FrontController

ASP.NET和JSP都是以Page路徑和URL一一對應,Web MVC要通過URL映射Controller和View,就需要一個前端控制器統一接收和解析請求,再根據的URL將請求分發到Controller。由于ASP.NET和Java分別以IHttpHandler和Servlet作為核心,因此ASP.NET MVC和Spring MVC分別使用實現了對應接口的 MvcHandler 和 DispatcherServlet 作為前段控制器。

Java Web系列:Spring MVC 基礎

ASP.NET中通過HttpModule的實現類處理URL映射,UrlRoutingModule根據URL將請求轉發給前端控制器MvcHandler。Spring MVC中,則根據URL的配置,直接將請求轉發給前端控制器DispatcherServlet。

(2)URL和Contrller的映射

ASP.NET MVC將URL和Controller的映射規則存儲在 RouteCollection 中,前端控制器MvcHandler通過 IController 接口查找控制器。Spring MVC則通過 RequestMapping 和 Controller 注解標識映射規則,無需通過接口依賴實現控制i器。

(3)URL和View的映射

ASP.NET MVC 默認通過 RazorViewEngine 來根據URL和視圖名稱查找視圖,核心接口是 IViewEngine 。Spring MVC 通過 internalResourceViewResolver 根據URL和視圖名稱查找視圖,核心接口是 ViewResolver 。

3.Spring MVC快速上手

(1)Spring MVC初始化

ASP.NET MVC初始化需要我們在HttpApplication.Application_Start方法中注冊默認的URL和Controller規則,Spring MVC由于采用注解映射URL和Controller,因此沒有對應的步驟。ASP.NET在根web.config中配置了UrlRoutingModule可以將請求轉發給MvcHandler,Spring MVC我們需要我們配置DispatcherServlet以及其對應的URL來達到接管所有請求的目的,Spring已經利用Servlet3.0定義的ServletContainerInitializer機制,為我們提供了默認的AbstractAnnotationConfigDispatcherServletInitializer,只要只需要像繼承HttpApplication的MvcApplication一樣,寫一個MyWebApplicationInitializer。

(2)URL和View的映射

ASP.NET的RazorViewEngine內置了View的Path和擴展名.cshtml的規則。Spring MVC的internalResourceViewResolver沒有提供默認值,因此如果我們如果不定義Path和擴展名,只需要MyWebApplicationInitializer即可。一般我們會指定將View放置在統一的視圖目錄中,使用特定的擴展名。Spring同樣提供了DelegatingWebMvcConfiguration,我們只需寫一個自己的AppConfig繼承它,重寫configureViewResolvers方法即可。完整的代碼如下:

package s4s;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

public class MyWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

@Configuration
@ComponentScan
class AppConfig extends DelegatingWebMvcConfiguration {

    @Override
    protected void configureViewResolvers(ViewResolverRegistry registry) {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        registry.viewResolver(viewResolver);
    }
}

(3)URL和Controller的映射

上文提到過Spring MVC和ASP.NET MVC的不同,不通過IController接口標識Controller,也不通過RouteCollection定義URL和Controller,取而代之的是兩個注解:Controller和RequestMapping。我們簡單的定義一個POJO MyController以及其簡單的Home方法。并應用上述注解:

package s4s;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {

    @RequestMapping("/")
    public String Home() {
        return "home";
    }
}

添加/WEB-INF/views/home.jsp視圖文件,就完成了最簡單的示例。無需web.xml的任何配置。

(4)使用Model

ASP.NET將視圖最終編譯為WebViewPage<object>,View和Model是一一對應并且類型匹配的,Model可以是任意的POCO。Spring MVC中View和Model是一對多的,提供了ModelMap和其子類ModelAndView提供類似ASP.NET MVC中ViewResult的功能。ModelMap的基類是LinkedHashMap<String, Object>。

我們修改MyController的代碼,使用ModelAndView來傳遞一個簡單UserModel模型,作為參數的UserModel對象model和ASP.NET MVC中一樣,會自動將請求參數映射到model的屬性。返回值ModelAndView時和ASP.NET MVC的return View(viewName,model)類似。只不過因為Spring MVC模型是多個模型的列表,我們還需要指定返回模型的Name。

package s4s;

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

@Controller
public class MyController {
    @RequestMapping("/")
    public ModelAndView Home(@ModelAttribute UserModel model) {
        model.setUserName(model.getUserName() + "~");
        return new ModelAndView("home", "model", model);
    }
}

class UserModel {
    String userName = "";

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

(5)使用View

修改home.jsp,添加jstl和spring的tag支持。由于Spring MVC中的View和ASP.NET MVC中的區別較大,沒有辦法指定View持有的Model類型也就沒有了智能提示和錯誤檢測的優勢,一切回歸到了腳本語言的時代。

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <h2>spring tag</h2>
    <form action="<%=request.getContextPath()%>" method="get">
        <spring:bind path="model.userName">
            <input type="text" name="userName" value="${status.value}" />
        </spring:bind>
        <input type="submit" value="submit">
    </form>
    <h2>spring form tag</h2>
    <form:form modelAttribute="model" method="get">
        <form:input path="userName" />
        <input type="submit" value="submit">
    </form:form>
</html>

附上pom.xml。其中junit是可選的,jstl是View中使用jstl語法需要引入的。

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>me.test</groupId>
    <artifactId>s4s</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>s4s Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>s4s</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

View Code

4.Spring MVC的初始化機制

(1)應用初始化:

Spring實現了Servlet 3.0規范定義的javax.servlet.ServletContainerInitializer接口并通過javax.servlet.annotation.HandlesTypes注解引用了WebApplicationInitializer接口。因此在Servlet容器初始化時,在當前class path路徑下的WebApplicationInitializer實現類的onStartup方法會自動執行(這和ASP.NET的Application_Start作用類似,在系列中的Java Web基礎時曾經提到過)。

(2)依賴注入的初始化:

ASP.NET中我們在Application_Start中初始化依賴注入容器。在Spring MVC中,我們實現WebApplicationInitializer接口同樣可以執行依賴注入的初始化。在Web環境中,我們使用的ApplicationContext接口的實現類為基于注解的AnnotationConfigWebApplicationContext(在系列中的Spring依賴注入基礎中曾經提到過),但我們無需直接實現WebApplicationInitializer并手動初始化AnnotationConfigWebApplicationContext對象,因為Spring已經定義了AbstractAnnotationConfigDispatcherServletInitializer作為WebApplicationInitializer接口的實現類,已經包含了AnnotationConfigWebApplicationContext的初始化。

(3)依賴注入配置:

采用基于Annotation注解時可以通過@ Configurateion 指定POJO來替代web.xml配置依賴注入。同樣,@ComponentScan可以替代web.xml中的掃描配置功能,使用ComponentScan配合Configurateion可以達到0xml配置的方式。上文中提到的Contrller相關的注解,都是啟用ComponentScan后才會被掃描生效。

(4)DispatcherServlet的初始化:

AbstractAnnotationConfigDispatcherServletInitializer類的父類AbstractDispatcherServletInitializer中已經包含DispatcherServlet的初始化。相關類圖如下:

Java Web系列:Spring MVC 基礎

5.Spring MVC的Action Filter

.NET MVC提供了眾多Filter接口和一個ActionFilterAttribute抽象類作為Filter的基礎,其中以實現了IAuthorizationFilter接口的AuthorizeAttribute攔截器最為我們熟知。Spring MVC則提供了基于HandlerInterceptor接口的眾多接口、抽象類和實現類,其中也有和.NET MVC類似的權限驗證UserRoleAuthorizationInterceptor攔截器。內置的攔截器可以滿足大部分需求,為了省事圖就畫在一張上了,上面是Spring MVC的,下面是.NET MVC的。 Java Web系列:Spring MVC 基礎

關于模型驗證和權限驗證的部分以后再續。

來自: http://www.cnblogs.com/easygame/p/5082647.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!