日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring MVC-01循序渐进之Model 2和MVC

發布時間:2025/3/21 javascript 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring MVC-01循序渐进之Model 2和MVC 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  • 概述
  • 模型1和模型2
  • 模型2架構圖
  • 模型2之Servlet控制器
    • Product類
    • ProductForm類
    • ControllerServlet類
    • 視圖
    • 測試應用
  • Maven配置文件
  • 源碼

概述

Java Web開發中有兩種設計模式

  • 模型1:頁面中心,適合小應用的開發

  • 模型2:基于MVC模式,是Java Web的推薦框架

本篇博文我們將通過3個不同的示例來介紹模型2和MVC模式

  • 第一個示例為基本的模型2應用,使用Servlet控制

  • 第二個示例引入了控制器

  • 第三個示例則引入了驗證控件來檢驗用戶的輸入


模型1和模型2

還記得初次學習JSP,通常通過鏈接的方式進行頁面之間的跳轉,非常直接,但是如果一個JSP頁面修改了名稱,在大中型項目中會帶來很大的維護問題,因此在實際的運用中并不推薦使用模型1。

模型2基于 模型—視圖—控制器(MVC)模式,該模式是Smalltalk-80用戶交互的核心概念。

一個實現了MVC模式的應用包含模型、視圖和控制器3個模塊。

  • 視圖負責應用的展示

  • 模型封裝了應用的數據和業務邏輯

  • 控制器負責接收用戶的輸入,改變模型以及調整視圖的顯示

模型2中,Servlet或者filter都可以充當控制器。 在Spring MVC 和 Struts1中送Servlet作為控制器,而Struts2中則使用一個Filter作為控制器。

大部分視圖都采用JSP作為應用的視圖,當然也有其他技術。

而模型則采用POJO(Plain Old Java Object), 是一個普通對象。

實踐中會采用一個JavaBean來持有模型狀態,并將業務邏輯放到一個Action類中。一個JavaBean必須擁有一個無參的構造函數,通過get/set來訪問參數,同時支持持久化。


模型2架構圖

我們來看下模型2應用的架構圖

我們來分析一下:

  • 每個HTTP請求都發給控制器,請求中的URI標識出對應的action。 action代表了應用可以執行的一個操作。

  • 一個Action的Java對象稱為Action對象,一個Action可以支持多個action(在Spring MVC以及Struts2中)或者一個action(Structs1 中)。

舉個簡單的例子: 添加產品,需要兩個action

  • 顯示“添加產品”表單,以便用戶輸入信息
  • 將表單信息保存到數據庫中
  • 如上所述,我們需要通過URI的方式告訴控制器來執行相應的action, 比如通過

    http://domain/appName/product_input

    來顯示“添加產品”表單

    通過如下URI

    http://domain/appName/product_save

    來保存產品。

    控制器會解析URI并調用對應的Action,然后將模型對象放到視圖可以訪問的區域(以便服務端數據可以展示在瀏覽器上),最后,控制器利用RequestDispatcher跳轉到視圖(JSP頁面),用表達式語言以及定制標簽來顯示數據。

    注意:調用RequestDispatcher.forward方法并不會停止執行剩余的代碼,因此,若forward方法不是最后一行代碼,則應該顯式的返回


    模型2之Servlet控制器

    為了便于對模型二有個直觀的了解,我們展示一個簡單的應用。實際中模型二非常復雜。

    我們的demo如下所示

    http://localhost:8080/chapter02a/product_input.action

    demo支持如下的兩個action

    • 展示“添加產品”表單。該action發送如上圖中輸入表單到瀏覽器,其對應的URI應包含字符串product_input

    • 保存產品并返回如下圖所示的完成頁面,對應的URI必須包含字符串product_save

    http://localhost:8080/chapter02a/product_save.action


    工程結構:

    • 一個Product類,作為product的領域對象
    • 一個ProductForm類,封裝了HTML表單的輸入項
    • 一個ControllerServlet類,控制器
    • 兩個JSP頁面作為View(都在WEB-INF下確保無法直接訪問到,必須通過Servlet來跳轉)
    • 一個CSS文件,定義了頁面的顯示風格

    Product類

    Product實例是一個封裝了產品信息的JavaBean.
    包含3個屬性,name、description、price

    package com.artisan.learnmvc.model;import java.io.Serializable; public class Product implements Serializable {private static final long serialVersionUID = 748392348L;private String name;private String description;private float price;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public float getPrice() {return price;}public void setPrice(float price) {this.price = price;} }

    Product類實現了Serializable接口,其實例可以安全的將數據保存到HTTPSession中。


    ProductForm類

    ProductForm表單類與HTML表單相映射,是后者在服務端的代表。

    ProductForm用來保存HttPServletRequest類中傳遞過來的值,因為HttPServletRequest只能是字符串,所以ProductForm類中所有的屬性都是String 。注意Product中的price是float,ProductForm是String類型

    ProductForm類看上去和Product類相同,那么有沒有存在的必要呢?

    實際上,表單對象會傳到ServletRequest給其他組件,類似Validator,而ServletRequest是一個Servlet層的對象不應該暴露給應用的其它層。

    另外一個原因是:當數據校驗失敗時,表單對象將用于保存和展示在原始表單上的輸入。

    注意:大部分情況,一個表單類不需要實現Serializable接口,因為表單對象很少保存在HttPSession中

    package com.artisan.learnmvc.form;public class ProductForm {private String name;private String description;private String price;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getPrice() {return price;}public void setPrice(String price) {this.price = price;} }

    ControllerServlet類

    ControllerServlet類繼承自javax.servlet.http.HttpServlet. 其中doGet和doPOST方法都最終調用自定義的process方法,該方法是整個Servlet控制器的核心。

    按照約定,所有的Servlet類名稱都帶有servlet后綴。

    package com.artisan.learnmvc.servlet;import java.io.IOException;import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import com.artisan.learnmvc.form.ProductForm; import com.artisan.learnmvc.model.Product;/*** * @author Mr.Yang* @Desc ControllerServlet類繼承自javax.servlet.http.HttpServlet. * 其中doGet和doPOST方法都最終調用自定義的process方法,該方法是整個Servlet控制器的核心。**/ public class ControllerServlet extends HttpServlet {private static final long serialVersionUID = 1579L;@Overridepublic void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException {process(request, response);}@Overridepublic void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException {process(request, response);}private void process(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException {String uri = request.getRequestURI();/** uri is in this form: /contextName/resourceName, * for example: /chapter02a/product_input. * However, in the event of a default context, the * context name is empty, and uri has this form* /resourceName, e.g.: /product_input*/int lastIndex = uri.lastIndexOf("/");String action = uri.substring(lastIndex + 1);// execute an actionif (action.equals("product_input.action")) {// no action class, there is nothing to be done} else if (action.equals("product_save.action")) {// create formProductForm productForm = new ProductForm();// populate action propertiesproductForm.setName(request.getParameter("name"));productForm.setDescription(request.getParameter("description"));productForm.setPrice(request.getParameter("price"));// create modelProduct product = new Product();product.setName(productForm.getName());product.setDescription(productForm.getDescription());try {product.setPrice(Float.parseFloat(productForm.getPrice()));} catch (NumberFormatException e) {}// code to save product// store model in a scope variable for the viewrequest.setAttribute("product", product);}// forward to a viewString dispatchUrl = null;if (action.equals("product_input.action")) {dispatchUrl = "/WEB-INF/jsp/ProductForm.jsp";} else if (action.equals("product_save.action")) {dispatchUrl = "/WEB-INF/jsp/ProductDetails.jsp";}if (dispatchUrl != null) {RequestDispatcher rd =request.getRequestDispatcher(dispatchUrl);rd.forward(request, response);}} }

    如果是Servlet3.0 ,可以使用注解的方式,比如

    @WebServlet(name="ControllerServlet",urlPatterns = {"/product_input","/product_save"}) public class ControllerServlet extends HttpServlet { ..... }

    我們來分析下ControllerServlet的process方法處理所有的輸入請求。

    1. 首先是獲取請求的URI和action名稱

    String uri = request.getRequestURI();int lastIndex = uri.lastIndexOf("/");String action = uri.substring(lastIndex + 1);

    2. 緊接著,process方法執行如下步驟

    • 創建并根據請求參數構造一個表單對象。product_save操作涉及3個屬性 name description 和price,然后創建一個領域對象,并通過表單對象設置相應屬性。

    • 執行針對領域對象的業務邏輯,包括持久化到數據庫中

    • 轉發請求到視圖

    詳見代碼部分。

    web.xml中配置Servlet

    <?xml version="1.0" encoding="ISO-8859-1"?> <web-app 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_3_0.xsd"version="3.0"> <servlet><servlet-name>ControllerServlet</servlet-name><servlet-class>com.artisan.learnmvc.servlet.ControllerServlet</servlet-class></servlet><servlet-mapping><servlet-name>ControllerServlet</servlet-name><url-pattern>*.action</url-pattern></servlet-mapping></web-app>

    視圖

    兩個視圖

    • ProductForm.jsp 對應product_input的操作
    • ProductDetails.jsp對應product_save的操作,通過EL表達式語言訪問HTTPServletRequest中的product對象。

    都采用了位于css目錄下的main.css中的CSS樣式進行控制

    <!DOCTYPE HTML> <html> <head> <title>Add Product Form</title> <style type="text/css">@import url(css/main.css);</style> </head> <body><div id="global"> <form action="product_save.action" method="post"><fieldset><legend>Add a product</legend><p><label for="name">Product Name: </label><input type="text" id="name" name="name" tabindex="1"></p><p><label for="description">Description: </label><input type="text" id="description" name="description" tabindex="2"></p><p><label for="price">Price: </label><input type="text" id="price" name="price" tabindex="3"></p><p id="buttons"><input id="reset" type="reset" tabindex="4"><input id="submit" type="submit" tabindex="5" value="Add Product"></p></fieldset> </form> </div> </body> </html> <!DOCTYPE HTML> <html> <head> <title>Save Product</title> <style type="text/css">@import url(css/main.css);</style> </head> <body> <div id="global"><h4>The product has been saved.</h4><p><h5>Details:</h5>Product Name: ${product.name}<br/>Description: ${product.description}<br/>Price: ${product.price}</p> </div> </body> </html>

    測試應用

    我們使用tomcat的8080端口,運行服務,訪問

    http://localhost:8080/chapter02a/product_input.action

    完成輸入后,表單提交到服務器URL上

    http://localhost:8080/chapter02a/product_save.action


    Maven配置文件

    <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.artisan</groupId><artifactId>chapter02a</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>chapter02a 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><scope>provided</scope><!-- provided 依賴只有在當JDK 或者一個容器已提供該依賴之后才使用。 例如, 如果你開發了一個web 應用,你可能在編譯 classpath 中需要可用的Servlet API 來編譯一個servlet,但是你不會想要在打包好的WAR 中包含這個Servlet API;這個Servlet API JAR 由你的應用服務器或者servlet 容器提供。已提供范圍的依賴在編譯classpath (不是運行時)可用。它們不是傳遞性的,也不會被打包。 --></dependency></dependencies><build><finalName>chapter02a</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.5.1</version><configuration><source>1.7</source><target>1.7</target><compilerArgument>-Xlint:all</compilerArgument><showWarnings>true</showWarnings><showDeprecation>true</showDeprecation></configuration></plugin></plugins></build> </project>

    源碼

    代碼已提交到github

    https://github.com/yangshangwei/SpringMvcTutorialArtisan

    總結

    以上是生活随笔為你收集整理的Spring MVC-01循序渐进之Model 2和MVC的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。