SpringMVC 概述
SSM 簡介
SSM 三層架構
-
表現層:負責資料展示
-
業務層:負責業務處理
-
資料層:負責資料操作
MVC 簡介
MVC(Model View Controller)是一種用於設計及建立 Web 應用程式表現層的模式。
-
Model(模型):資料模型,用於封裝資料
-
View(檢視):頁面檢視,用於展示資料
- jsp
- html
-
Controller(控制器):處理使用者互動的排程器,用於根據使用者需求處理程式邏輯
- Servlet
- SpringMVC
SpringMVC 簡介
SpringMVC 是一種基於 Java 實現的、MVC 模型的、輕量級的 Web 框架。
SpringMVC 優點:
- 使用簡單
- 效能突出(相比現有的框架技術)
- 靈活性強
入門案例
SpringMVC 工作流程分析:
- 伺服器啟動:
- 載入 web.xml 中 DispatcherServlet;
- 讀取 spring-mvc.xml 中的配置,載入所有 com 包中所有標記為 bean 的類;
- 讀取 bean 中方法上方標註 @RequestMapping 的內容;
- 處理請求:
- DispatcherServlet 配置攔截所有請求“/”;
- 使用請求路徑與所有載入的 @RequestMapping 的內容進行比對;
- 執行對應的方法;
- 根據方法的返回值在 webapp 目錄中查詢對應的頁面並展示。
實現示例:
- 匯入 SpringMVC 相關的 Maven 依賴:
<!-- servlet3.1規範的座標 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp座標-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<!--spring的座標-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--spring web的座標-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<!--springmvc的座標-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
- 定義表現層處理器 Controller(等同於 Servlet),並配置成 Spring 的 bean:
@Controller
public class UserController {
public void save(){
System.out.println("user mvc controller is running ...");
}
}
- 定義 SpringMVC 配置檔案(格式與 Spring 配置檔案一致):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!--掃描載入所有的控制類類-->
<context:component-scan base-package="com"/>
</beans>
- web.xml 中配置 SpringMVC 核心控制器,用於將請求轉發到對應的具體業務處理器 Controller 中(等同於 Servlet 配置):
<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*:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 設定具體 Controller 的訪問路徑與返回頁面(等同於 Servlet 在 web.xml 中的配置):
// 設定當前方法的訪問對映地址
@RequestMapping("/save")
// 設定當前方法返回值型別為String,用於指定請求完成後跳轉的頁面
public String save(){
System.out.println("user mvc controller is running ...");
// 設定具體跳轉的頁面
return "success.jsp";
}
Spring 技術架構
DispatcherServlet(前端控制器)
:是整體流程控制的中心,由其呼叫其它元件處理使用者的請求,有效降低了元件間的耦合性。- HandlerMapping(處理器對映器):負責根據使用者請求找到對應具體的 Handler 處理器。
Handler(處理器)
:業務處理的核心類,通常由開發者編寫,描述具體的業務。- HandlAdapter(處理器介面卡):通過它對處理器進行執行。
- View Resolver(檢視解析器):將處理結果生成 View 檢視。
View(檢視)
:最終產出結果,常用檢視如 jsp、html。
SpringMVC 基礎配置
常規配置
Controller 載入控制
SpringMVC 的處理器對應的 bean 必須按照規範格式開發,為了避免加入無效的 bean,可通過 bean 載入過濾器進行包含設定或排除設定。
例如,表現層 bean 標註通常設定為 @Controller,因此可以通過註解名稱進行過濾控制:
<context:component-scan base-package="com">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
靜態資源載入
<!--放行指定型別靜態資源配置方式-->
<mvc:resources mapping="/img/**" location="/img/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<!--SpringMVC提供的通用資源放行方式-->
<mvc:default-servlet-handler/>
中文亂碼處理
web.xml:
<!-- 亂碼處理過濾器,與Servlet中使用的完全相同,差異之處在於處理器的類由Spring提供 -->
<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>
註解驅動
目標:刪除 web.xml 和 spring-mvc.xml 。
注意:
實現示例:
- 使用註解形式,將 SpringMVC 核心配置檔案替換為配置類:
package com.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.Controller;
@Configuration
@ComponentScan(
value="com",
includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes={Controller.class})
)
public class SpringMvcConfig implements WebMvcConfigurer {
// 註解配置放行指定資源格式
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/img/**").addResourceLocations("/img/");
// registry.addResourceHandler("/js/**").addResourceLocations("/js/");
// registry.addResourceHandler("/css/**").addResourceLocations("/css/");
// }
// 註解配置通用放行資源的格式
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();;
}
}
- 替換 web.xml:基於 servlet3.0 規範,自定義 Servlet 容器初始化配置類,載入 SpringMVC 核心配置類
package com.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.EnumSet;
import java.util.Objects;
public class ServletInitConfig extends AbstractDispatcherServletInitializer {
/*
建立 Servlet 容器時,使用註解的方式載入 SpringMVC 配置類中的資訊,並載入成 Web 專用的 ApplicationContext 物件
該物件放入了 ServletContext 範圍,後期在整個 Web 容器中可以隨時獲取呼叫
*/
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
// 註解配置對映地址方式,服務於 SpringMVC 的核心控制器 DispatcherServlet
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
// 亂碼處理作為過濾器,在 servlet 容器啟動時進行配置
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(Objects.<ServletContext>requireNonNull(servletContext));
CharacterEncodingFilter cef = new CharacterEncodingFilter();
cef.setEncoding("UTF-8");
FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef);
registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD,
DispatcherType.INCLUDE), false, "/*");
}
}
請求
請求對映:@RequestMapping
@RequestMapping 使用:
- 型別:類註解;方法註解
- 位置:處理器類定義上方;處理器類中的方法定義上方
- 作用:為當前處理器中所有方法設定公共的訪問路徑字首;繫結請求地址與對應處理方法間的關係
// 示例:方法註解
@Controller
public class UserController {
// 訪問 URI:/user/requestURL1
@RequestMapping("/requestURL1")
public String requestURL2() {
return "page.jsp";
}
}
// 示例:類註解
@Controller
@RequestMapping("/user")
public class UserController {
// 訪問 URI:/user/requestURL2
@RequestMapping("/requestURL2")
public String requestURL2() {
return "page.jsp";
}
}
常用屬性:
@RequestMapping(
value="/requestURL3", // 設定請求路徑,與path屬性、value屬性相同
method = RequestMethod.GET, // 設定請求方式
params = "name", // 設定請求引數條件
headers = "content-type=text/*", // 設定請求訊息頭條件
consumes = "text/*", // 用於指定可以接收的請求正文型別(MIME型別)
produces = "text/*" // 用於指定可以生成的響應正文型別(MIME型別)
)
public String requestURL3() {
return "/page.jsp";
}
普通型別傳參
// URL 訪問:http://localhost:8080/requestParam1?name=xiaoming&age=14
@RequestMapping("/requestParam1")
public String requestParam1(String name ,String age){
System.out.println("name="+name+", age="+age);
return "page.jsp";
}
@RequestParam
- 型別:形參註解
- 位置:處理器類中的方法形參前方
- 作用:繫結請求引數與處理方法形參間的關係
示例:
// http://localhost:8080/requestParam2?userName=Jock
@RequestMapping("/requestParam2")
public String requestParam2(@RequestParam(
name = "userName",
required = true,
defaultValue = "xiaohuang") String name) {
System.out.println("name="+name);
return "page.jsp";
}
- 當未傳參即直接訪問“/requestParam2”時,方法會取預設值“xiaohuang”。
- 當配置了“required=true”但未配置“defaultValue”時,訪問時不傳參則會報 400 錯。
物件型別傳參
POJO
當使用 POJO(簡單 Java 物件)時,傳參名稱與 POJO 類屬性名保持一致即可。
- POJO 類:
package com.bean;
public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
- Controller:
// URL 訪問:http://localhost:8080/requestParam3?name=xiaodong&age=18
@RequestMapping("/requestParam3")
public String requestParam3(User user){
System.out.println("name="+user.getName());
return "page.jsp";
}
引數衝突
當 POJO 的屬性與其他形參出現同名問題時,將被同時賦值。
// 訪問 URL:http://localhost:8080/requestParam4?name=xiaoyi&age=14
@RequestMapping("/requestParam4")
public String requestParam4(User user, String age){
System.out.println("user.age="+user.getAge()+", age="+age); // user.age=14, age=14
return "page.jsp";
}
建議使用 @RequestParam 註解進行區分。
複雜物件型別
當物件中出現物件屬性時,則要求入參名稱與物件層次結構名稱保持一致。
物件集合
1)當複雜物件中出現用 List 儲存物件資料時,要求入參名稱與物件層次結構名稱保持一致,並使用陣列格式描述集合中物件的位置。
- bean:
public class User {
private String name;
private Integer age;
private List<Address> addresses;
}
public class Address {
private String province;
private String city;
private String address;
}
- Controller:
// 訪問URL:http://localhost:8080/requestParam7?addresses[0].province=bj&addresses[1].province=tj
@RequestMapping("/requestParam7")
public String requestParam7(User user){
System.out.println("user.addresses="+user.getAddresses());
return "page.jsp";
}
注意:The valid characters are defined in RFC 7230 and RFC 3986
問題解決
2)當複雜物件中出現用 Map 儲存物件資料時,要求入參名稱與物件層次結構名稱保持一致,並使用對映格式描述集合中物件的位置。
- bean:
public class User {
private String name;
private Integer age;
private Map<String, Address> addressMap;
}
public class Address {
private String province;
private String city;
private String address;
}
- controller:
// 訪問 URL:http://localhost:8080/requestParam8?addressMap['home'].province=bj&addressMap['job'].province=tj
@RequestMapping("/requestParam8")
public String requestParam8(User user){
System.out.println("user.addressMap="+user.getAddressMap());
return "page.jsp";
}
陣列集合型別傳參
// 訪問 URL:http://localhost:8080/requestParam9?nick=xiaoming1&nick=xiaoming2
@RequestMapping("/requestParam9")
public String requestParam9(String[] nick){
System.out.println(nick[0]+", "+nick[1]); // xiaoming1, xiaoming2
return "page.jsp";
}
// 訪問 URL:http://localhost:8080/requestParam10?nick=xiaoming1&nick=xiaoming2
@RequestMapping("/requestParam10")
public String requestParam10(@RequestParam("nick") List<String> nick){
System.out.println(nick); // [xiaoming1, xiaoming2]
return "page.jsp";
}
注意:
-
SpringMVC 預設將 List 作為物件處理,賦值前先建立物件,然後將 nick 作為物件的屬性進行處理。而由於 List 是介面,無法建立物件,報無法找到構造方法異常;修復型別為可建立物件的 ArrayList 型別後,物件可以建立,但沒有 nick 屬性,因此資料為空。
-
此時需要告知 SpringMVC 的處理器 nick 是一組資料,而不是一個單一資料。
-
因此通過 @RequestParam 註解,將數量大於 1 個的 names 引數打包成引數陣列後, SpringMVC 才能識別該資料格式,並判定形參型別是否為陣列或集合,並按陣列或集合物件的形式運算元據。
型別轉換器
SpringMVC 會對接收的引數進行自動型別轉換,該工作通過 Converter 介面實現。
標量轉換器:
- StringToBooleanConverter String —> Boolean
- ObjectToStringConverter Object —> String
- StringToNumberConverterFactory String —> Number( Integer、Long 等)
- NumberToNumberConverterFactory Number子型別之間(Integer、Long、Double 等)
- StringToCharacterConverter String —> java.lang.Character
- NumberToCharacterConverter Number子型別(Integer、Long、Double 等) —> java.lang.Character
- CharacterToNumberFactory java.lang.Character —> Number 子型別(Integer、Long、Double 等)
- StringToEnumConverterFactory String —> enum 型別
- EnumToStringConverter enum 型別 —> String
- StringToLocaleConverter String —> java.util.Local
- PropertiesToStringConverter java.util.Properties —> String
- StringToPropertiesConverter String —> java.util.Properties
集合、陣列相關轉換器:
- ArrayToCollectionConverter 陣列 —> 集合(List、Set)
- CollectionToArrayConverter 集合(List、Set) —> 陣列
- ArrayToArrayConverter(陣列間轉換)
- CollectionToCollectionConverter 集合間(List、Set)
- MapToMapConverter Map間
- ArrayToStringConverter 陣列 —> String 型別
- StringToArrayConverter String —> 陣列(實現方式為 trim 後使用 "," 進行 split)
- ArrayToObjectConverter 陣列 —> Object
- ObjectToArrayConverter Object —> 單元素陣列
- CollectionToStringConverter 集合(List、Set) —> String
- StringToCollectionConverter String —> 集合(List、Set)(實現方式為 trim 後使用 "," 進行 split)
- CollectionToObjectConverter 集合 —> Object
- ObjectToCollectionConverter Object —> 單元素集合
預設轉換器:
- ObjectToObjectConverter(Object 間轉換)
- IdToEntityConverter Id —> Entity
- FallbackObjectToStringConverter Object —> String
日期型別格式轉換
配置版:宣告自定義的轉換格式並覆蓋系統轉換格式
<!-- 啟用自定義Converter -->
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- 1.設定格式型別Converter,註冊為Bean,受SpringMVC管理 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 2.自定義Converter格式型別設定,該設定使用的是同型別覆蓋的思想 -->
<property name="formatters">
<!-- 3.使用set保障相同型別的轉換器僅保留一個,避免衝突 -->
<set>
<!-- 4.設定具體的格式型別 -->
<bean class="org.springframework.format.datetime.DateFormatter">
<!-- 5.型別規則 -->
<property name="pattern" value="yyyy-MM-dd"/>
</bean>
</set>
</property>
</bean>
註解版:
- 名稱:@DateTimeFormat
- 型別:形參註解、成員變數註解
- 位置:形參前面或成員變數上方
- 作用:為當前引數或變數指定型別轉換規則
- 注意:依賴註解驅動支援(<mvc:annotation-driven />)
- 範例:
// 形參前
// 訪問 URL:http://localhost:8080/requestParam11?date=2021-12-12
@RequestMapping("/requestParam11")
public String requestParam11(@DateTimeFormat(pattern="yyyy-MM-dd") Date date){
System.out.println("date="+date);
return "page.jsp";
}
// 成員變數上方
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
自定義型別轉換器
1)實現 Converter 介面,並制定轉換前與轉換後的型別:
- 配置:
<!-- 1.將自定義Converter註冊為Bean,受SpringMVC管理 -->
<bean id="myDateConverter" class="com.itheima.converter.MyDateConverter"/>
<!-- 2.設定自定義Converter服務bean -->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<!-- 3.注入所有的自定義Converter,該設定使用的是同型別覆蓋的思想 -->
<property name="converters">
<!-- 4.set保障同型別轉換器僅保留一個,去重規則以Converter<S,T>的泛型為準 -->
<set>
<!-- 5.具體的型別轉換器 -->
<ref bean="myDateConverter"/>
</set>
</property>
</bean>
- 實現類:
// 自定義型別轉換器,實現Converter介面,介面中指定的泛型即為最終作用的條件
// 本例中的泛型填寫的是<String,Date>,最終出現字串轉日期時,該型別轉換器生效
public class MyDateConverter implements Converter<String, Date> {
// 重寫介面的抽象方法,引數由泛型決定
public Date convert(String source) {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
// 型別轉換器無法預計使用過程中出現的異常,因此必須在型別轉換器內部捕獲,不允許丟擲,框架無法預計此類異常如何處理
try {
date = df.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
2)通過註冊自定義轉換器,將該功能加入到 SpringMVC 的轉換服務 ConverterService 中:
<!-- 開啟註解驅動,載入自定義格式化轉換器對應的型別轉換服務 -->
<mvc:annotation-driven conversion-service="conversionService"/>
響應
頁面跳轉:轉發與重定向
// 轉發
@RequestMapping("/showPage1")
public String showPage1() {
System.out.println("user mvc controller is running ...");
return "forward:page.jsp"; // 支援訪問WEB-INF下的頁面
}
// 重定向
@RequestMapping("/showPage2")
public String showPage2() {
System.out.println("user mvc controller is running ...");
return "redirect:page.jsp"; // 不支援訪問WEB-INF下的頁面
}
請求轉發與重定向的區別:
-
當使用請求轉發時,Servlet 容器將使用一個內部的方法來呼叫目標頁面,新的頁面繼續處理同一個請求,而瀏覽器將不會知道這個過程(即伺服器行為)。與之相反,重定向的含義是第一個頁面通知瀏覽器傳送一個新的頁面請求。因為當使用重定向時,瀏覽器中所顯示的 URL 會變成新頁面的 URL(瀏覽器行為)。而當使用轉發時,該 URL 會保持不變。
-
重定向的速度比轉發慢,因為瀏覽器還得發出一個新的請求。
-
同時,由於重定向產生了一個新的請求,所以經過一次重定向後,第一次請求內的物件將無法使用。
總結:
- 重定向:兩次請求,瀏覽器行為,位址列改變,請求域中的資料會丟失。
- 請求轉發:一次請求,伺服器行為,位址列不變,請求域中的資料不丟失。
怎麼選擇是重定向還是轉發呢?
-
通常情況下轉發更快,而且能保持請求內的物件,所以它是第一選擇。但是由於在轉發之後,瀏覽器中 URL 仍然指向開始頁面,此時如果過載當前頁面,開始頁面將會被重新呼叫。如果不想看到這樣的情況,則選擇重定向。
-
不要僅僅為了把變數傳到下一個頁面而使用 session 作用域,那會無故增大變數的作用域,轉發也許可以幫助解決這個問題。
- 重定向:以前的請求中存放的變數全部失效,並進入一個新的請求作用域。
- 轉發:以前的請求中存放的變數不會失效,就像把兩個頁面拼到了一起。
頁面訪問快捷設定(InternalResourceViewResolver)
通常,展示頁面的儲存位置比較固定且結構相似,因此可以設定通用的訪問路徑,來簡化頁面配置。
示例:
<!-- 設定頁面載入的字首字尾,僅適用於預設形式,不適用於手工標註轉發或重定向的方式 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
public String showPage3() {
return "page";
}
而如果未設定返回值,使用 void 型別,則預設使用訪問路徑來拼接前字尾:
// 最簡頁面配置方式:使用訪問路徑作為返回的頁面名稱,省略返回值
@RequestMapping("/showPage5")
public void showPage5() {
System.out.println("user mvc controller is running ...");
}
帶資料頁面跳轉
public class Book {
private String name;
private Double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
import com.bean.Book;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
@Controller
public class BookController {
// 使用原生response物件響應資料
@RequestMapping("/showData1")
public void showData1(HttpServletResponse response) throws IOException {
response.getWriter().write("message");
}
// 使用原生request物件傳遞引數
@RequestMapping("/showPageAndData1")
public String showPageAndData1(HttpServletRequest request) {
request.setAttribute("name", "xiaoming");
return "page";
}
// 使用Model形參傳遞引數
@RequestMapping("/showPageAndData2")
public String showPageAndData2(Model model) {
Book book = new Book();
book.setName("SpringMVC入門案例");
book.setPrice(66.66d);
// 新增資料的方式
model.addAttribute("name", "xiaoming");
model.addAttribute("book", book);
return "page";
}
// 使用ModelAndView形參傳遞引數,該物件還封裝了頁面資訊
@RequestMapping("/showPageAndData3")
public ModelAndView showPageAndData3(ModelAndView modelAndView) {
// ModelAndView mav = new ModelAndView(); // 替換形參中的引數
Book book = new Book();
book.setName("SpringMVC入門案例");
book.setPrice(66.66d);
// 新增資料的方式
modelAndView.addObject("book", book);
modelAndView.addObject("name", "xiaoming");
// 設定返回頁面(若該方法存在多個,則以最後一個為準)
modelAndView.setViewName("page");
// 返回值設定成ModelAndView物件
return modelAndView;
}
// ModelAndView物件支援轉發的手工設定,該設定不會啟用字首字尾的頁面拼接格式
@RequestMapping("/showPageAndData4")
public ModelAndView showPageAndData4(ModelAndView modelAndView) {
modelAndView.setViewName("forward:/WEB-INF/pages/page.jsp");
return modelAndView;
}
// ModelAndView物件支援重定向的手工設定,該設定不會啟用字首字尾的頁面拼接格式
@RequestMapping("/showPageAndData5")
public ModelAndView showPageAndData6(ModelAndView modelAndView) {
modelAndView.setViewName("redirect:index.jsp");
return modelAndView;
}
}
返回 JSON 資料
- 匯入 maven 座標:
<!--json相關座標3個-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
- Controller:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
// 使用@ResponseBody將返回的結果作為響應內容,而非響應的頁面名稱
@RequestMapping("/showData2")
@ResponseBody
public String showData2(){
return "{\"name\":\"xiaoming\"}";
}
// 使用jackson進行json資料格式轉化(會有中文亂碼問題)
@RequestMapping("/showData3")
@ResponseBody
public String showData3() throws JsonProcessingException {
Book book = new Book();
book.setName("SpringMVC入門案例");
book.setPrice(66.66d);
ObjectMapper om = new ObjectMapper();
return om.writeValueAsString(book);
}
/*
<!--開啟springmvc註解驅動,對@ResponseBody的註解進行格式增強,追加其型別轉換的功能,具體實現由MappingJackson2HttpMessageConverter進行-->
<mvc:annotation-driven/>
*/
// 使用SpringMVC註解驅動,對標註@ResponseBody註解的控制器方法進行結果轉換
// 由於返回值為引用型別,自動呼叫jackson提供的型別轉換器進行格式轉換
@RequestMapping("/showData4")
@ResponseBody
public Book showData4() {
Book book = new Book();
book.setName("SpringMVC入門案例");
book.setPrice(66.66d);
return book;
}
// 轉換集合型別資料
@RequestMapping("/showData5")
@ResponseBody
public List showData5() {
Book book1 = new Book();
book1.setName("SpringMVC入門案例");
book1.setPrice(66.66d);
Book book2 = new Book();
book2.setName("SpringMVC入門案例");
book2.setPrice(66.66d);
ArrayList<Book> al = new ArrayList<>();
al.add(book1);
al.add(book2);
return al; // 返回 [{"name":"SpringMVC入門案例","price":66.66},{"name":"SpringMVC入門案例","price":66.66}]
}
Servlet 相關介面
SpringMVC 提供訪問原始 Servlet 介面 API 的功能,通過形參宣告即可。
@RequestMapping("/servletApi")
public String servletApi(HttpServletRequest request,
HttpServletResponse response, HttpSession session){
System.out.println(request); // org.apache.catalina.connector.RequestFacade@6d3a1615
System.out.println(response); // org.apache.catalina.connector.ResponseFacade@55405578
System.out.println(session); // org.apache.catalina.session.StandardSessionFacade@714a7020
request.setAttribute("name", "xiaoming");
System.out.println(request.getAttribute("name")); // xiaoming
return "page.jsp";
}
Header 資料獲取:
- 名稱:@RequestHeader
- 型別:形參註解
- 位置:處理器類中的方法形參前方
- 作用:繫結請求頭資料與對應處理方法形參間的關係
// header 資料獲取
@RequestMapping("/headApi")
public String headApi(@RequestHeader("Accept-Language") String head){
System.out.println(head); // zh-CN,zh;q=0.9
return "page.jsp";
}
Cookie 資料獲取:
- 名稱:@CookieValue
- 型別:形參註解
- 位置:處理器類中的方法形參前方
- 作用:繫結請求 Cookie 資料與對應處理方法形參間的關係
// cookie 資料獲取
@RequestMapping("/cookieApi")
public String cookieApi(@CookieValue("JSESSIONID") String jsessionid){
System.out.println(jsessionid);
return "page.jsp";
}
Session 資料獲取:
- 名稱:@SessionAttribute
- 型別:形參註解
- 位置:處理器類中的方法形參前方
- 作用:繫結請求 Session 資料與對應處理方法形參間的關係
// 測試用方法,為下面的試驗服務,用於在session中放入資料
@RequestMapping("/setSessionData")
public String setSessionData(HttpSession session){
session.setAttribute("name", "xiaoming");
return "page";
}
// session 資料獲取
@RequestMapping("/sessionApi")
public String sessionApi(@SessionAttribute("name") String name){
System.out.println(name); // 獲取session中的name值
return "page.jsp";
}
Session 資料設定:
- 名稱:@SessionAttributes
- 型別:類註解
- 位置:處理器類上方
- 作用:宣告放入 session 範圍的變數名稱,適用於 Model 型別資料傳參
@Controller
// 設定當前類中名稱為age和gender的變數放入session範圍(不常用,瞭解即可)
@SessionAttributes(names={"age","gender"})
public class ServletController {
// 配合 @SessionAttributes(names={"age","gender"}) 使用
// 將資料放入session儲存範圍,通過Model物件實現資料set,通過@SessionAttributes註解實現範圍設定
@RequestMapping("/setSessionData2")
public String setSessionDate2(Model model) {
model.addAttribute("age",39);
model.addAttribute("gender","男");
return "page.jsp";
}
}