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";
}
}