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也會很簡單。當然,表面上運用都是簡單的,複雜的運用還很多呢。
如果世界這麼簡單就好了。
好了,下期再會!