1. 程式人生 > 實用技巧 >Spring MVC學習筆記(一)

Spring MVC學習筆記(一)

注:學習筆記,比較雜亂

Spring MVC業務處理流程

DAO層、Service層和Controller層

1、DAO層

資料訪問層(data access object),具體到對某張表的增刪改查,某一DAO一定對應著資料庫中的某張表。在DAO層應該只做增刪改查操作。

2、Service層

服務層,對一個或多個DAO的再次封裝,封裝成一個服務。需要進行事務控制。

3、Controller層

負責請求轉發,接受頁面發過來的引數,傳遞給Service處理,接到返回結果在傳遞給頁面。

總結:DAO面向表,Service面向業務。後端開發時先設計出資料庫中的表,再針對每一張表設計出DAO層,然後根據具體的業務邏輯進一步把DAO封裝成Service層,對外提供一個服務。

SpringMVC開發環境搭建——IDEA版(Maven)

1、使用Maven建立專案

左側選擇“Maven”,在右側勾選“Create from archetype(意思是從原型建立)”,在左側原型列表中找到“maven-archetype-webapp ”並選中,點選Next。不要忘記選擇合適的SDK。

輸入Name(專案名)和GroupId(一般是公司名),點選Next。

設定Maven屬性。在Properties裡新增一組鍵值對“archetypeCatalog-internal”,解決maven專案建立過慢的問題。點選finish。

2、補全目錄結構。Maven專案的目錄結構是固定的,但是創建出來的專案目錄結構是不全的,所以需要手動補全。在src-main目錄上右鍵,new-Directory,在彈出的視窗選擇Java,新增Java目錄;再用同樣的方式新增resources目錄(IDEA2020.1.2版本,不能這麼新增的可以手動輸入java和resources新增,然後右鍵java目錄“Make Directoryas --Source Root”;右鍵resources目錄“MakeDirectoryas --Resources Root)。

=======>>>

3、修改專案pom.xml配置檔案,引入SpringMVC依賴。將<maven.compiler.source>和<maven.compiler.target>兩個標籤中的內容改為使用的JDK版本。並新增<Spring.Version>標籤。如下所示。

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>14</maven.compiler.source>
    <maven.compiler.target>14</maven.compiler.target>
    <spring.version>5.0.2.RELEASE</spring.version>
  </properties>

在專案pom.xml檔案的<dependencies>標籤內填入以下程式碼:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>

4、配置前端控制器(即servlet)。在src—main—webapp—WEB-INF—web.xml檔案內的<web-app>標籤內新增以下程式碼。其中,<servlet-class>標籤內的org.springframework.web.servlet.DispatcherServlet是固定的,<url-pattern>內的/表示攔截所有請求。兩個<xxx-name>標籤內可以隨便填寫,一般填寫類的小寫名稱。

  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

5、配置SpringMVC的配置檔案。在第2步建立的resources資料夾上New-XML Configuration File-Spring Config,命名為SpringMVC(名字隨便取,叫SpringMVC便於識別)

6、部署伺服器。點選右上角“Add Configuration”,點選彈出的視窗左上角的加號,選擇tomcat,然後選擇Deployment選項卡,點選右側的加號,選擇Artifact,在選擇“專案名:war”,刪掉“Application Context”中的內容(也可以不刪,如果不刪的話專案中的連結都要在前面加上Application Context裡的內容,我這裡沒刪,應該加上/SpringMVCLearn_war),點選OK,再點選OK。

編寫入門程式

1、刪掉src—main—webapp目錄下的index.jsp,新建index.html檔案

2、先在index.html檔案的body標籤內新增一個<h2>和<a>標籤,<a>標籤的href屬性先留空。程式碼如下:

<body>
<h2>入門程式</h2>
<a href="">入門程式</a>
</body>

3、建立後臺類。在src—main—java目錄下新建controller資料夾,建立一個 名為HelloController的類。

====>>>

4、在HelloController類上添加註解@Controller,將其標記為Controller。新增一個名問sayHello的方法,並添加註解@RequestMapping(path = "/hello")

package controller;

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

//控制器類
@Controllerpublic class HelloController {

    @RequestMapping(path = "/hello")  //url應為“/SpringMVCLearn_war/hello”,如果Application Context內的內容刪掉了,則url為“/hello”
    public String sayHello() {
        System.out.println("Hello SpringMVC");
        return "success";
    }
}

5、在webapp目錄下新建一個名為HTML的資料夾,存放.html檔案。在新建的HTML資料夾內新建一個名為success.html的檔案,隨便寫點東西。

6、修改SpringMVC.xml配置檔案,開啟註解掃描,並指定檢視解析器的尋找路徑。在SpringMVC.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:mvc="http://www.springframework.org/schema/mvc"
       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/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--開啟註解掃描-->
    <context:component-scan base-package="controller"></context:component-scan>

    <!-- 預設的註解對映 -->
    <mvc:annotation-driven />

    <!-- 解除servlet對靜態資原始檔訪問的限制,使得靜態資源先經過,必須設定,不然啟動時無法訪問主頁-->
    <mvc:default-servlet-handler />

    <!--檢視解析器物件:class是固定的-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--尋找檢視的路徑 此處要與上一步建立的資料夾路徑嚴格對應起來!!!!!!!-->
        <property name="prefix" value="/HTML/" /> 
        <!--尋找檔案的字尾名-->
        <property name="suffix" value=".html" />
    </bean>

</beans>

7、前端控制器(servlet)載入SpringMVC配置檔案。在web.xml檔案的<servlet>標籤內新增以下程式碼:

    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:SpringMVC.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>

最終web.xml檔案的內容為:

<!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>

  <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:SpringMVC.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>

</web-app>

8、在index.html的<a>標籤的href屬性內寫入“/SpringMVCLearn_war/hello”。

9、點選右上角啟動按鈕啟動。

註解

RequestMapping註解

作用:建立請求url和處理請求方法之間的對應關係

常用屬性:

  value與path:作用相同,指定對映路徑。如果只用了RequestMapping註解的一個屬性,可以省略引數名只寫路徑名

  method:指定請求方式。RequestMethod列舉類

  params:用於指定限制請求引數的條件,支援簡單的表示式。要求請求引數的key和value必須和配置的一模一樣

    例如:

      params={“accountName”},表示請求中必須有accountName

      params={“money!100”},表示請求引數中money不能是100

  headers:用於指定限制請求訊息頭的條件

  注意:以上4個屬性同時出現2個或以上時,它們之間是與的關係,即必須同時成立。

RequestParam註解

作用:把請求中指定名稱的引數給控制器中的形參賦值

常用屬性:

  value:請求引數中的名稱

  required:請求引數中是否必須提供此引數。預設值:true,表示必須提供,如果不提供將報錯。

  例如:

<a href="/hello?name=hahaha"></a>
    @RequestMapping(path = "/hello")
    public String sayHello(@RequestParam("name") String userName) {
        System.out.println(userName);
        return "success";
    }

RequestBody註解

作用:用於獲取請求體的內容。直接使用得到的是key=value&key=value……結構的資料。不適用於get請求,因為get請求沒有請求體。

屬性:

  required:是否必須有請求體。預設值是:true。當取值為true時,get請求方式會報錯。如果取值為false,get請求得到null。

PathVariable註解

作用:用於繫結url中的佔位符。例如:請求url中/delete/{id},這個{id}就是url佔位符。url支援佔位符是Spring3.0之後加入的,是SpringMVC支援rest風格URL的重要標誌。

屬性:

  name和value:用於指定url中佔位符的名稱。

  required:指定是否必須提供佔位符。

  例如:

<a href="/PathVariable/10">PathVariable註解</a>
    @RequestMapping("/PathVariable/{id}")
    public String testPathVariable(@PathVariable(name = "id") String id) {
        System.out.println(id);
        return "success";
    }

上述程式碼後臺會輸出"10"

RequestHeader註解

作用:用於獲取請求訊息頭。(一般用不到此註解)

屬性:

  value:提供訊息頭名稱。

  required:是否必須有此訊息頭。

CookieValue註解

作用:用於把指定cookie名稱的值傳入控制器方法引數。

屬性:

  value:指定cookie的名稱。

  required:指定是否必須有此cookie。

ModelAttribute註解(此註解可能已過期,帶查閱資料確定)

作用:該註解是SpringMVC4.3版本引入的,它可以用於修飾方法和引數。該註解修飾方法時,表示當前方法會在控制器的方法執行之前先執行。它可以修飾沒有返回值的方法,也可以修飾有返回值的方法。出現在引數上時,獲取指定的資料給引數賦值。

屬性:

  value:用於獲取資料的key。key可以是POJO的屬性名稱,也可以是map結構的key。

應用場景:

  當表單提交資料不是完整的實體類資料時,保證沒有提交資料的欄位使用資料庫物件原來的資料。

  例如:

    我們在編輯一個使用者時,使用者有一個建立資訊欄位,該欄位的值是不允許被修改的。在提交表單時肯定沒有此欄位的內容,一旦更新會把該欄位內容置為null,此時就可以使用此註解解決問題。

SessionAttributes註解(在html中不太好用,待解決或尋找其他方式,例如Ajax)

作用:用於多次執行控制器方法間的引數共享

屬性:

  value:用於指定存入的屬性名稱。

  type:用於指定存入的資料型別。

請求引數的繫結

1、後臺方法會自動接收傳遞的url中與方法引數名相同的引數,例如:

    @RequestMapping("paramsTest")
    public String ParamsMethod(String user,String pwd){
        /**/
        System.out.println(user);
        System.out.println(pwd);
        return null;
    }

如果傳遞過來的url為“***/paramsTest?user=song&pwd=123456,則後臺會列印song(即user)和123456(即pwd)

2、使用JavaBean繫結

java類:

package domain;

import java.io.Serializable;

public class Account implements Serializable {
    private String userName;
    private String password;
    private double money;

    private User user;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "Account{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                ", money=" + money +
                ", user=" + user +
                '}';
    }
}
/**
 * @author :宋慶國
 * @date :Created in 2020/7/5 21:37
 * @modified By:
 */
package domain;

import java.io.Serializable;

public class User implements Serializable {
    private String uname;
    private Integer age;

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "uname='" + uname + '\'' +
                ", age=" + age +
                '}';
    }
}

頁面表單:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>JavaBean引數繫結</h2>
<form action="/saveAccount" method="post">
    姓名:<input type="text" name="userName"/><br> <!--name的值嚴格對應Account類的屬性名-->
    密碼:<input type="text" name="password"/><br>
    金額:<input type="text" name="money"/><br>
    使用者姓名:<input type="text" name="user.uname"/><br>  <!--Account類中還有個User引用型別的例項,要想給這個User類傳遞引數,應使用此類"例項名.屬性名"-->
    使用者年齡:<input type="text" name="user.age"/><br>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

Controller類:

package controller;

import domain.Account;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ParamsBind {
    /*
     * 請求引數繫結,把資料封裝到JavaB的類中
     *
     * */
    @RequestMapping("/saveAccount")
    public String saveAccount(Account account) {
        System.out.println(account.toString());
        return "success";
    }
}

配置解決中文亂碼的過濾器

在web.xml中新增以下程式碼:

    <!--配置解決中文亂碼的過濾器-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>