同樣的MVC,不同的實現方法(Spring MVC .Net MVC)


由於工作需要,最近將Net的MVC又重新好好的學習了一遍.學習教材是博客園里的大神的作品《ASP.NET MVC5框架揭秘》。

《ASP.NET MVC5框架揭秘》這本書,說了很多東西,但是總覺得太偏於理論,實際的例子太少。當然,框架揭秘 的確就應該是這個樣子的,畢竟不是什么MVC的速成書籍。

公司以后接的活,其實不僅限於NET平台,JAVA平台也需要考慮的,所以,當前階段Java的知識儲備也是必須的。這篇文章和語言之爭無關,希望不要引起大家的無謂的爭論。學習SpringMVC使用的是ITEYE的大神 開濤的MVC系列教程,版本是Spring MVC2.5/3.0(最新版本是 4.1.2)

環境搭建:

VisualStudio不愧是宇宙第一IDE,NET MVC5的HelloWorld,就是傻瓜式的選選項目類型,然后按下F5就一切搞定了。

MVC5不但把后台的東西幫你准備好了,連前端的框架都替你決定了,bootstrap,Modernize,Jquery。然后你會看到package里面有一大堆東西,

ORM用的,前端用的,JSON,所有的東西都Standby了。如果哪位同學不喜歡bootstrap,想用UIKit,好吧,自己重寫所有的模板吧。

自動生成的所有模板都是基於bootstrap的。然后Shard的TemplateEditor目錄下面就會出現很多類似BooleanExEditor這樣子的東西了。

Spring MVC

Java小白,只會用Elcapse,然后看教程,寫了個HelloWorld。

國內的教程,大都將初學者的水平想得太高了,大段大段的XML配置文件加上簡單的注解,就完事了。

最大的,最主要的目錄結構,半句話都沒有,你讓我這樣的小白,將一大堆xml配置文件放在什么地方好呢。最后只能yahoo.co.jp

找到一篇島國人民的MVC入門文章,搞清楚了目錄結構 http://qiita.com/siguremon/items/84c831391a6204079fd2

島國人民寫出來的入門教程,就是將學習對象當小白處理。然后教材寫得是變態般的詳細。目標是讓歐巴和歐巴桑看了都能夠編程。

[Maven和Nuget]

.NET有Nuget,Java這里有Maven,Maven的一個功能和Nuget一樣,管理依賴項目。

在Maven的幫助下,Spring的MVC所需要的東西,也能夠快速的准備齊全。

下面這個pom.xml里面包含了MySql的JDBC的導入

<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>com.shchuwa</groupId>
    <artifactId>springmvc</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>springmvc Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>  
        <springframework.version>4.1.2.RELEASE</springframework.version>  
    </properties> 
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>springmvc</finalName>
    </build>
</project>

Spring的包,其實東西也不少JUnit,AOP,Log。。。

接管HTTP控制權

NET的MVC是通過HttpHandler在IIS管道中獲得控制權的,讓Route部件參與IIS管道,如果Route能匹配的話,就讓MVC接手后續的所有事件。

這個過程在NETMVC的大神的書的第一章里說明得很好了。大部分人可能會覺得第一章無所謂,對於開發無關痛癢,但是,往往一些根本性的東西就在第一章里面。

Spring,其實也是差不多的思路,dispatcherServlet這個Servlet(org.springframework.web.servlet.DispatcherServlet)通過配置文件將自己作為Http的處理入口,Tomcat也好,JBoss也好,Apache也好,直接將Http請求轉交給dispatcherServlet處理了。

掌握入口的感覺真心不錯,能處理的處理,不能處理的,交給默認的Servlet處理

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
        http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
        ">
    <display-name>spring-todo</display-name>
    <!-- (1) -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath:/META-INF/spring/beans-webmvc.xml
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- (2) -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

 關於路由

NET的MVC里面,有一個專門注冊路由的地方,博客園都是MVC的高手,這里就不再啰嗦了。

所有的路由規則都統一放在一起管理,直接了當,一目了然。

Spring的Route規則是通過注解(NET的特性)的方式,寫在Controller中的。

注意:RequestMapping就是Spring的路由

Spring在初始化的時候,會掃描指定位置下面所有的類,如果有@Controller的注解,就將其記錄為Controller

然后會解析@RequestMapping,構建類似於RouteTable這樣的東西。

而NET的話,約定了所有的Controller都放在指定的目錄下面。都繼承於Controller父類/接口。

當然,編碼習慣好的Javer,也會把所有Controller放在同一個目錄/Package的。

 

package controller;

import static org.springframework.web.bind.annotation.RequestMethod.GET;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import model.person;
// (1)
@Controller
public class HelloWorldController {
    // (2)
    @RequestMapping(value = "/", method = GET)
    public String home(ModelMap model) {
        // (3)
        person.insert();
           model.addAttribute("message", "Spring 3 MVC Hello World");  
        return "helloworld";
    }
}

 

 

對於Controller的啟動條件,除了GET/POST這樣的檢查之外,Spring的條件貌似更加豐富一些。NET的MVC是否有同樣功能,我不知道。(或許可以使用攔截器)

1.可以要求請求的URL里面有某個參數(或者沒有某個參數),進而可以控制參數的值是否等於某個值。

 

2.可以對請求類型進行控制。例如,下面是請求一個Json的例子,這里同時對Url和請求類型進行限制

 

@RequestMapping(value="/header/test3", headers = "Content-Type=application/json"):

 

數據綁定和驗證

數據綁定這塊,兩者的處理都差不多,如果一個數據類型可以和字符進行相互轉換,那么系統就會自動幫你做綁定。

如果不行的話,自己寫一個類型和字符的轉換類即可。

NET大神用的是 Point(int x,int y)的例子

Sping 大神用的是 PhoneNumber(int AreaCode,int Number)的例子。

一句話,內置的能轉的類型,系統幫你做綁定,不能轉的類型,你告訴我一個字符到類型的雙向變換規則,然后注冊到系統里面去,我也負責給你綁定。

Pattern pattern = Pattern.compile("^(\\d{3,4})-(\\d{7,8})$");
@Override
public void setAsText(String text) throws IllegalArgumentException {
if(text == null || !StringUtils.hasLength(text)) {
setValue(null); //如果沒值,設值為null
}
Matcher matcher = pattern.matcher(text);
if(matcher.matches()) {
PhoneNumberModel phoneNumber = new PhoneNumberModel();
phoneNumber.setAreaCode(matcher.group(1));
phoneNumber.setPhoneNumber(matcher.group(2));
setValue(phoneNumber);
} else {
throw new IllegalArgumentException(String.format("類型轉換失敗,需要格式
[010-12345678],但格式是[%s]", text));
}
}
@Override
public String getAsText() {
PhoneNumberModel phoneNumber = ((PhoneNumberModel)getValue());
return phoneNumber == null ? "" : phoneNumber.getAreaCode() + "-" +
phoneNumber.getPhoneNumber();
}

內置的驗證約束注解:

MVC.NET使用的應該是自己的東西,

Spring 使用的是Hibernate Validator,能夠檢查的東西都差不多吧。沒有仔細研究。

題外話:NET里面的數據模型叫Model,Spring里面貌似叫做命令對象:Spring大神的原文如下

數據綁定:請求參數綁定到一個command object(命令對象,非GoF里的命令設計模式),這里的命令對象是指綁
定請求參數的任何POJO 對象;

攔截器

Spring 和Net一樣都提供了攔截器來處理AOP

package org.springframework.web.servlet;
public interface HandlerInterceptor {
boolean preHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler)
throws Exception;
void postHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView)
throws Exception;
void afterCompletion(
HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex)
throws Exception;
}

前兩個沒有什么好說的,處理前,處理后,最后一個NET中不知道怎么處理的。作用如下:

afterCompletion:整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中我們可以在此記錄結束時間
並輸出消耗時間,還可以進行一些資源清理,類似於try-catch-finally中的finally,但僅調用處理器執行鏈中preHandle
返回true的攔截器的afterCompletion。

當然,Spring的攔截器也提供了取消功能,如果取消的話,整個處理就中止了(break)。攔截器的思想都差不多的,大家實現思想也都類似。

 

由於Spring在學習中,可能有理解錯誤的地方,希望大家指正。公司現在正在招募前端工程師,有興趣的可以發個簡歷。工作地點是上海。

(更多內容以后更新)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM