1. 程式人生 > >JavaWeb框架-SpringMVC-1-沒有對比,就沒有傷害啊~

JavaWeb框架-SpringMVC-1-沒有對比,就沒有傷害啊~

話說

親愛的讀者們,晚上好!SSH框架總結完畢後,今天初步總結下SpringMVC,我們依次總結了Hibernate==》Struts2==》Spring,今天邀請的明星是:SpringMVC!回頭看看,就會發現總結順序都有內在邏輯。在環境搭建、傳參方面,今天的主角無疑簡單得不能再簡單。框架就是讓底層東西越來越淺顯易懂,類似快餐,可以讓你很方便、很快滴吃飽。閒話少說,言歸正傳。

目錄:

1、整體佈局
2、環境搭建
3、引數傳遞
4、總結

因為筆者部落格連貫性很強,所以每次都會重複寫下開發環境,避免中途來參觀的讀者不知所云
IntelliJ IDEA(2017.2.5)
Maven Web專案

1、整體佈局

這裡寫圖片描述

2、環境搭建

1、導包
2、配置web.xml
3、Controller層測試
3、配置springmvc-servlet.xml
4、頁面

1) 導包

因為SpringMVC是基於Spring的,所有匯入spring-context、spring-mvc、spring-web這三個包。

<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.hmc.springmvc02</groupId> <artifactId>springmvc02</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>springmvc02 Maven Webapp</name> <url>http://maven.apache.org</url
>
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!--Spring context--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.1.RELEASE</version> </dependency> <!--Spring mvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.1.RELEASE</version> </dependency> <!--Spring web--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.0.1.RELEASE</version> </dependency> </dependencies> <build> <finalName>springmvc02</finalName> </build> </project>

2) 配置web.xml

這一步非常核心。我們請求頁面得第一站就是web,所以你訪問的引數,怎麼讓springMVC來管理呢?就是通過這個DispatcherServlet類來管理的。一旦頁面敲下類似**.htm的請求,馬上就去找DispatchServlet去處理,處理過程是和註解結合起來的,所以當你要指定呼叫方法的時候,一切就那麼連貫起來了。

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>


  <!--配置Spring MVC 核心-->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>


</web-app>

3) Controller層測試

BookAction

這個Controller主要演示註解和方法呼叫。

package com.hmc.springmvc.controller;

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

/**
 * User:Meice
 * 2017/11/9
 */
@Controller
public class BookAction {

    @RequestMapping(name = "/list.htm")
    public String list() {
        System.out.println("顯示圖書列表");
        return "list";
    }

  /*  @RequestMapping(name = "/add.htm")
    public String add() {
        System.out.println("新增了圖書");
        return "add";

    }
*/

   /* @RequestMapping(name = "/update.htm")
    public String update() {
        System.out.println("修改了圖書");
        return "update";

    }*/

    @RequestMapping("/del.htm")
    public void del() {
        System.out.println("刪除了圖書");
    }

}

我們訪問頁面,目的是呼叫方法,進行業務邏輯處理。怎麼呼叫指定方法?過濾器就起作用了,首先過濾到,然後通過你在對應的方法上加的註解,就去找和註解名字相同的方法,調動後,如何返回頁面呢?

這裡就牽扯到了檢視解析器。這個檢視解析器,類似我們配置的struts2.xml.一會再做對比。先看如何配置的?

要想讓註解生效,首先是需要掃描包的。這裡還要提一下springMVC配置檔案的命名規則,一般都是servlet-name+servlet.xml這種命名方式,而且要放到WEB-INF下面,否則提示:

java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/springmvc-servlet.xml]

在下的servlet-name是springmvc,所以這個配置檔名:springmvc-servlet.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:aop="http://www.springframework.org/schema/aop"
       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/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--掃描包註解-->
    <context:component-scan base-package="com.hmc.springmvc"/>

    <!--Spring檢視解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

之所以能夠找到頁面,而不至於走丟,核心在於這個類:InternalResourceViewResolver
配置方式淺顯易懂,類似struts2.xml。想當年,我們在Struts2中想呼叫方法和返回介面,是這麼配置的:

 <!--配置-->
        <action name="Book_list" class="com.hmc.struts2.action.BookAction" method="list">
            <result name="success">/WEB-INF/Book/list.jsp</result>
        </action>

當然,採用萬用字元是這麼配置的:

 <action name="*_*" class="com.hmc.struts2.action.BookAction" method="${2}">
            <result name="success">/WEB-INF/{1}/{2}.jsp</result>
        </action>

還要開啟DynamicMethodInvocation及全域性方法匹配就不在贅述。
所以,對比起來,springMVC理解起來還是很容易滴。

4) 配置springmvc-servlet.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:aop="http://www.springframework.org/schema/aop"
       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/aop
                http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--掃描包註解-->
    <context:component-scan base-package="com.hmc.springmvc"/>

    <!--Spring檢視解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

5) 頁面

很簡單,取值就行。注意IDEA預設新建的JS頁面EL表示式是關閉的,所以要開啟:IsELIgnored=”false”,不然你看到的全都是${}

<%--
  User: Meice
  Date: 2017/11/9
  Time: 15:59
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>圖書列表</title>
</head>
<body>
    <h2>圖書列表介面</h2>

    使用者名稱:【${username}】<br/>
    密碼:【${pwd}】<br/>

    物件:<br/>
    ${book}<br/>
    【${book.name}】

<hr/>


</body>
</html>

3、引數傳遞

LoginController
傳參:傳單個引數與傳物件。
這裡傳參更加簡單。直接把屬性作為方法引數即可,如果是個物件,直接用Map或者Model就可以。

package com.hmc.springmvc.controller;
import com.hmc.springmvc.model.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;

/**
 * User:Meice
 * 2017/11/9
 */
@Controller
public class LoginController {

    /**
     * SpringMVc 傳參
     */


    @RequestMapping("/login.htm")
    public String login(@RequestParam(name = "username") String username, String pwd,@RequestParam int age) {
        System.out.println("使用者名稱:"+username+"\t"+"密碼:"+pwd);
        return "list";
    }
    /**
     * 以上存在問題:
     * 1)中文亂碼?
     * 2)如果使用者名稱和密碼都為空,也會提交使用者名稱:   密碼: ?
     * 如何必須填寫後才能登入?
     * 當然前提是密碼是String型別,預設為空串,假如密碼為int pwd,那麼不填寫,頁面就無法跳轉,因為預設的空串
     * 是無法自動轉換為int型別的
     *
     * 3、@RequestParam 可以對必須要填寫的引數做限制,否則報錯
     * But,@RequestParam(name = "username") String username這是沒有效果的,因為預設為空串,還是可以的
     * 只是針對Null值才有效。
     *
     * 如果沒有填寫,報錯:HTTP Status 400 - Required int parameter 'age' is not present
     */


    /**
     * 傳參
     */


    //傳參法一:Map<>
    @RequestMapping("/login.htm")
    public String login(String username, String pwd, Map<String,Object> ctx) {
        System.out.println("使用者名稱:"+username+"密碼:"+pwd);
        ctx.put("username",username);
        ctx.put("pwd",pwd);


        //傳入物件
        Book book = new Book(3,"《三國演義》");
        ctx.put("book",book);

        return "list";
    }

    //傳參法二:Model

      @RequestMapping("/login.htm")
    public String list(String username, String pwd, Model model) {
        System.out.println("使用者名稱:"+username +"  密碼:"+pwd);
        model.addAttribute("username",username);
        model.addAttribute("pwd",pwd);

        //傳參-物件
        Book book = new Book(1,"《紅樓夢》");
        model.addAttribute(book);

        return "list";
    }

    /**
     * Book{id=1, name='《紅樓夢》'}
     * 由此發現,Model的底層還不是Map集合
     */

}

來來,這裡我們要回憶下這這幾個傳參方式:我們從遙遠的Servlet說起:
Servlet是這麼傳參的:

    request.setAttribute();

Struts2有3種傳參方式:

1)定義屬性,生成set()方法;

2)定義物件,生成set()方法,頁面用物件.屬性;

3)定義物件為屬性,然後實現ModelDriven,實現方法。中間傳參用到了這個:

ActionContext.getContext.put();

我們的springMVC怎麼傳參呢?So Easy! 如果是不多的屬性,直接給方法帶參,引數名和介面表單元素name一致即可;若是物件,使用Model或者Map集合即可。Model本質還是個Map集合,放進去就是Put的事情,人家內部封裝好了,引數直接就過去了。因為是轉發請求,所以引數可以帶過去。怎麼帶過去滴?問框架嘍~

而且,頁面直接取值,即便是集合,也可以直接.屬性,而不用區分什麼key,value之類的。所以EL表示式是真正的強大!

4、總結

1、框架那麼多,木有對比,就木有“傷害”。對比了解,瞭解框架進化過程,會更好的理解框架本身;為什麼要這麼演化,怎麼簡化的,才是技術思想精進的真諦;

2、環境搭建時,springMVC是基於Spring的,web.xml方面依託的是DispatcherServlet;檢視層servlet.xml,依靠的是檢視解析器,主要是這個類:IntervalResourceViewResolver;

3、呼叫方法通過加註解@RequestMapping()即可,返回字串就是對應頁面即可;

4、引數傳遞。直接給對應方法帶參即可,如果引數過多,就用物件。儲存值就通過Map集合和Model來實現。

很簡單,到後面的MyBatis也會很簡單。當然,表面上運用都是簡單的,複雜的運用還很多呢。

如果世界這麼簡單就好了。

好了,下期再會!