SpringMVC实例

来源:互联网 发布:易语言用数据库做登录 编辑:程序博客网 时间:2024/05/21 22:27
http://magicma-007.iteye.com/blog/1536325

Table of Contents 
Spring MVC 

1. 簡介 

Spring MVC是一個和Spring完美結合的Web框架。我先前學過Struts2,再學Spring MVC,覺得Spring MVC更為簡約、高效和優雅,它有不少東西借鑒自Struts2,如依賴注入等。它功能完整,推薦在新項目中替代Struts2,至於Struts,直接 秒殺。 

下面的配置均采用Spring 3版本,Spring MVC基於Java Servlet技術規範,主要處理流程圖: 



來自瀏覽器的請求URL由DispatcherServlet統一處理(除了css、js、圖片等靜態文件),它符合Java Servlet規範。在web.xml文件中配置哪些URL由該Servlet處理。 
DispatcherServlet根據配置(通常由註解或xml文件配置)將URL請求發往相應的Controller處理,這個過程會帶上服務器端傳遞過來的參數並自動裝載給Controller。 
Controller接收到參數後,調用相應的方法處理之,方法裡可以調用業務層接口或數據層接口等,然後將處理結果打包到一個ModelAndView對象中並返回。 
DispatcherServlet將ModelAndView對象發往視圖解析器viewResolver處理。 
視圖解析器根據ModelAndView對象中指定的視圖模板位置和攜帶的數據渲染模板文件為html文件,返回渲染後的文件。 
DispatcherServlet將html文件(有時候是純文本或多媒體文件)返回給瀏覽器。 
很好的教程:點擊 

2. 安裝及配置文件 

建議使用eclipse或netbeans編寫程式,只需要導入Spring和Spring Web的所有jar包即可。 

按照習慣,Spring的xml配置文件統一放在classpath根目錄下並遵循applicationContext-*.xml的命名規 範;web.xml配置css、js、圖片文件為靜態文件,靠後綴識別,其它URL由DispatcherServlet處理。web.xml配置文件如 下。 

不要使用/js/*作為靜態文件的url-pattern,這樣可以直接訪問WEB-INF下的文件。 

web.xml 
<?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"> 

<!-- 解決亂碼問題 --> 
<filter> 
<filter-name>characterEncodingFilter</filter-name> 
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
<init-param> 
<param-name>encoding</param-name> 
<param-value>utf8</param-value> 
</init-param> 
<init-param> 
    <param-name>forceEncoding</param-name> 
    <param-value>true</param-value> 
</init-param> 
</filter> 
<filter-mapping> 
<filter-name>characterEncodingFilter</filter-name> 
<url-pattern>/*</url-pattern> 
</filter-mapping> 

<!-- 配置靜態文件 --> 
<servlet-mapping> 
<servlet-name>default</servlet-name> 
<url-pattern>*.css</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
<servlet-name>default</servlet-name> 
<url-pattern>*.js</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
<servlet-name>default</servlet-name> 
<url-pattern>*.jpg</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
<servlet-name>default</servlet-name> 
<url-pattern>*.jpeg</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
<servlet-name>default</servlet-name> 
<url-pattern>*.png</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
<servlet-name>default</servlet-name> 
<url-pattern>*.gif</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
<servlet-name>default</servlet-name> 
<url-pattern>*.bmp</url-pattern> 
</servlet-mapping> 

<!-- Spring MVC Servlet配置 --> 
<servlet> 
<servlet-name>dispatcherServlet</servlet-name> 
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
<init-param> 
<param-name>contextConfigLocation</param-name> 
<!-- 如果有多個spring配置文件,用逗號隔開 --> 
<param-value>classpath:applicationContext-*.xml</param-value> 
</init-param> 
<load-on-startup>1</load-on-startup> 
</servlet> 
<servlet-mapping> 
<servlet-name>dispatcherServlet</servlet-name> 
<url-pattern>/</url-pattern> 
</servlet-mapping> 

<welcome-file-list> 
<welcome-file>index.jsp</welcome-file> 
</welcome-file-list> 
</web-app> 
Tomcat, Jetty, JBoss, and GlassFish 默認Servlet的名字 – “default” 
Google App Engine 默認Servlet的名字 – “_ah_default” 
Resin 默認Servlet的名字 – “resin-file” 
WebLogic 默認Servlet的名字 – “FileServlet” 
WebSphere 默認Servlet的名字 – “SimpleFileServlet” 
classpath下關於Spring Web的配置文件: 

applicationContext-web.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" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
                    http://www.springframework.org/schema/context 
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 

<!-- 【注意】這裡設置所有Controller所在的包位置,該包中所有使用annotation的類都會自動加載 --> 
<context:component-scan base-package="springmvc.web" /> 

<!-- 
視圖解析器,由DispatcherServlet控制,根據Controller返回值選擇對應的模板 
具體:Controller返回modelAndView或String對象,由對象name前面加上prefix,後面加上subfix形成文件的真實地址 
--> 
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
<property name="prefix" value="/WEB-INF/jsp/" /> 
<property name="suffix" value=".jsp" /> 
</bean> 

<!-- 上傳文件 --> 
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/> 
</beans> 
3. 編寫Controller之Hello World 

3.1 編寫Controller 

Controller可以是任意一個普通類,不需要繼承或實現任何東西。Controller類必須放在配置文件applicationContext-web.xml中指定的註解包下,如springmvc.web,應根據實際情況修改。 

HelloWorldController.java 
package springmvc.web; 

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

// 通過註解使得該類變成Controller類 
@Controller 
// 根目錄,默認是"/",指定後為"/hello" 
@RequestMapping("hello") 
public class HelloWorldController { 

// 該方法對應的URL,即訪問"/hello/hello_world"將調用該方法 
@RequestMapping("hello_world") 
public ModelAndView handleRequest() { 

// modelAndView的名稱將會結合viewResolver配置的prefix和suffix合成一個頁面的路徑 
ModelAndView modelAndView = new ModelAndView("hello_world"); 
// modelAndView對象攜帶的信息 
modelAndView.addObject("message", "hello_world MVC!"); 
return modelAndView; 


        // 一個類中可以寫很多這樣的方法,名稱自取,使用註解映射到不同的URL 

        // 如果沒有附帶數據,也可以直接返回String類型的名稱 

關於其它bean依賴注入,比如業務層或數據層的對象,使用註解可以讓Spring完成自動注入: 

@Autowired 
private CommonDao commonDao; 
注意:ModelAndView的類不是org.springframework.web.portlet.ModelAndView 

3.2 編寫jsp頁面 

當請求鏈接”/hello/hello_world”發送到DispatcherServlet,轉發到 HelloWorldController的handlerRequest方法,該方法返回modelAndView對象,根據該對象的名稱 hello_world和配置文件中的prefix和suffix組合成物理jsp地址位置:/WEB-INF/jsp/hello_world.jsp 

現在創建該jsp頁面: 

hello_world.jsp 
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<html> 
  <body> 
<p>這是Controller傳過來的數據message:${message}</p> 
  </body> 
</html> 
modelAndView對象中附帶的message字符串將被渲染到jsp頁面中。 

部署該標準Java Web項目到tomcat服務器上,本機訪問http://127.0.0.1:8080/spring_mvc/hello/hello_world就可以看到網頁,其中spring_mvc是我在eclipse中的項目名稱,默認是這樣: 

这是Controller传过来的数据message:hello_world MVC! 
4. 獲得來自瀏覽器的參數及環境變量 

4.1 GET或POST傳遞的參數 

Spring MVC採用控制反轉的思想進行依賴注入,假設HTML頁面需要傳遞參數name和age,則HTML頁面有個form: 

<form action="/some/url"> 
Name: <input type="text" name="name"/><br /> 
Age:  <input type="text" name="age"/><br /> 
</form> 
這種提交形式是POST,也可以等同地使用GET方式提交:/some/url?name=pugwoo&age=24 

然後Controller中對應的方法只需要在參數上加上對應名稱和類型的參數: 

    @RequestMapping("/some/url") 
    public ModelAndView handleRequest(String name, Integer age) { 
        // 此時name和age已經擁有服務器端傳過來的值 
        // 類型也會自動轉換,比如從String轉成Integer 

        // 接下來,做你想做的事情 
    } 
如果想指定採用GET或POST方式,在@RequestMapping中指定method即可: 

@RequestMapping(value = "/url", method = RequestMethod.GET) 
或 
@RequestMapping(value = "/url", method = RequestMethod.POST) 
注:我不喜欢Spring 2.0使用Spring MVC标签来写HTML页面的方式。雖然它提供了參數驗證功能,但這個由自己寫的js來做更好,這樣有利於開發的解耦。 

類Struts2的OGNL傳參形式 

當頁面的變量很多時,可以採用OGNL方式傳遞變量,加入有類Car,Car有屬性String name和String model並提供對應的getter和setter方法,則HTML的<input>名稱可以寫為:”name”和”model”,然後在 Controller的對應方法的參數中只寫Car car,Spring MVC會將該對象及其值構建好。 

注意:<input>的name屬性不是填“car.name”,而是“name”。 

Date類型的參數傳遞問題 

頁面傳遞過來的數據均是String類型,爾後Spring將其轉化成對應類型。有些類型不是Spring默認可以轉換的,如Date。只需要在Controller.java代碼中加入一個binder方法即可: 

@InitBinder 
public void initBinder(WebDataBinder binder) { 
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); 
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); 

其中日期格式按照實際需要進行設置,如“yyyy-MM-dd HH:mm:ss”等。 

4.2 獲得Cookie的值 

在Controller對應的方法的參數使用@CookieValue註解獲得: 

    @RequestMapping("/some/url") 
    public ModelAndView handleRequest(@CookieValue("name") String name) { 
        // 接下來,做你想做的事情 
    } 
4.3 上传文件 

首先是HTML上傳頁面的form表格: 

      <form action="upload" method="post" enctype="multipart/form-data"> 
        <input type="file" name="myfile" /> 
        <input type="submit" /> 
      </form> 
然後編寫Controller,注意一定要加上@RequestParam,原因未明: 

UploadController.java 
package springmvc.web; 

import java.io.IOException; 

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

@Controller 
public class UploadController { 

    @RequestMapping("upload") 
    // 一定要加上@RequestParam 
    public ModelAndView uploadFile(@RequestParam MultipartFile myfile) throws IOException{ 
    ModelAndView modelAndView = new ModelAndView("result"); 

    // 顯示文件內容 
    StringBuilder sb = new StringBuilder(); 

// 判斷文件是否已上傳 
if (!myfile.isEmpty()) { 
sb.append("文件名稱: " + myfile.getOriginalFilename() + "<br/>"); 

String content = new String(myfile.getBytes()); 
content = content.replace("\n", "<br/>"); 
sb.append(content); 
} else { 
sb.append("沒有選擇文件"); 


    modelAndView.addObject("result", sb.toString()); 
    return modelAndView; 
    } 

然後新建一個/WEB-INF/result.jsp文件: 

result.jsp 
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<html> 
  <body> 
    <p>上傳的文件信息:</p> 
<p>${result}</p> 
  </body> 
</html> 
如果出現java.lang.NoClassDefFoundError: org/apache/commons/io/output/DeferredFileOutputStream異常,加上org.apache.commons.io包即可。 

4.4 獲得環境變量 

標準的Servlet規範中,有HttpServletRequest和HttpServletResponse等環節變量(關於這些變量的用途,請參見標準Servlet編程),Spring MVC可以很輕鬆地獲得,只需要像上面獲得參數一樣在方法參數中寫即可: 

    @RequestMapping("/some/url") 
    public ModelAndView handleRequest(HttpServletRequest request, 
HttpServletResponse response) { 

        // 你已獲得HttpServletRequest和HttpServletResponse對象,比Struts2實現***Aware接口還簡單 

        // 接下來,做你想做的事情 
    } 
5. REST形式的URL 

REST形式的URL對搜索引擎友好,看起來也很簡潔漂亮。Spring MVC實現REST形式URL很簡單,例子: 

/** 
* 在RequestMapping中,变量用{}括起来 
* 然后在处理方法中用@PathVariable获取,名称要一致 
* @PathVariable 里面也可以加上value="xxx",名称可以不一致 
*/ 
@RequestMapping("/{name}/page/{p}") 
public void handleRequest(Writer writer, @PathVariable String name, 
@PathVariable Integer p) throws IOException{ 
writer.write("you are reading " + name +"'s page " + p); 

URL中的數值會被作為變量傳入到方法中,如name和p,同樣是依賴注入的思想,類型會自動轉換,訪問下面的URL查看效果: 

http://127.0.0.1:8080/spring_mvc/pugwoo/page/1 
http://127.0.0.1:8080/spring_mvc/pugwoo/page/2 
http://127.0.0.1:8080/spring_mvc/nick/page/99 
6. 其它技巧 

輸出純文本 

例子,支持中文: 

@RequestMapping("test") 
public void test(HttpServletResponse resp) throws IOException { 
resp.setContentType("text/plain;charset=utf-8"); 
resp.getWriter().write("Test 測試中文"); 

該方法適合做cgi接口,輸出json等格式的數據。 

客戶端跳轉 

設定Controller對應的方法返回名稱“redirect:hello_world”即可跳轉到對應的頁面,如hello_world。浏览器的地址栏会变化。 

服務器端跳轉 

設定Controller對應的方法返回名稱“forward:hello_world”即可跳轉到對應的頁面,如hello_world。 

forward並不能將變量通過modelAndView傳遞給新的URL,只能通過將變量放在request或session裏面來完成。而對於redirect,變量只能放在session裏面,不能放在request裏。 

jsp頁面標籤jstl 

導入標籤: 

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
直接獲取某個變量的值:${message} 或 ${car.name} 等 

循環遍歷容器,假如有類Car,Car有屬性name並且提供getter方法,對象數組ArrayList<Car> cars,則java語句: 

for(Car car : cars) { 
  System.out.println(car.getName()); 

等同於 

<c:forEach items="${cars}" var="car"> 
    ${car.name} <br /> 
</c:forEach> 
亂碼問題 

上面的web.xml中已經解決了POST數據的亂碼問題,但是GET方式傳遞數據仍有亂碼,這是URL編碼的問題,需要在服務器容器端設置,以Tomcat為例,修改conf/server.xml文件對應位置新增“URIEncoding”: 

    <Connector port="8080" protocol="HTTP/1.1" 
               connectionTimeout="20000" 
               redirectPort="8443" URIEncoding="utf-8"/> 
修訂日誌 
0 0
原创粉丝点击