SpringMVC 入門、請求、響應



SpringMVC 概述

SSM 簡介

SSM 三層架構

  • 表現層:負責數據展示

  • 業務層:負責業務處理

  • 數據層:負責數據操作

image


MVC 簡介

MVC(Model View Controller)是一種用於設計及創建 Web 應用程序表現層的模式。

  • Model(模型):數據模型,用於封裝數據

  • View(視圖):頁面視圖,用於展示數據

    • jsp
    • html
  • Controller(控制器):處理用戶交互的調度器,用於根據用戶需求處理程序邏輯

    • Servlet
    • SpringMVC

image

SpringMVC 簡介

SpringMVC 是一種基於 Java 實現的、MVC 模型的、輕量級的 Web 框架。

SpringMVC 優點

  1. 使用簡單
  2. 性能突出(相比現有的框架技術)
  3. 靈活性強

入門案例

SpringMVC 工作流程分析:

  1. 服務器啟動:
    1. 加載 web.xml 中 DispatcherServlet;
    2. 讀取 spring-mvc.xml 中的配置,加載所有 com 包中所有標記為 bean 的類;
    3. 讀取 bean 中方法上方標注 @RequestMapping 的內容;
  2. 處理請求:
    1. DispatcherServlet 配置攔截所有請求“/”;
    2. 使用請求路徑與所有加載的 @RequestMapping 的內容進行比對;
    3. 執行對應的方法;
    4. 根據方法的返回值在 webapp 目錄中查找對應的頁面並展示。

實現示例

  1. 導入 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>
  1. 定義表現層處理器 Controller(等同於 Servlet),並配置成 Spring 的 bean:
@Controller
public class UserController {

    public void save(){
        System.out.println("user mvc controller is running ...");
    }
}
  1. 定義 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>
  1. 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>
  1. 設定具體 Controller 的訪問路徑與返回頁面(等同於 Servlet 在 web.xml 中的配置):
// 設定當前方法的訪問映射地址
@RequestMapping("/save")
// 設置當前方法返回值類型為String,用於指定請求完成后跳轉的頁面
public String save(){
    System.out.println("user mvc controller is running ...");
    // 設定具體跳轉的頁面
    return "success.jsp";
}

Spring 技術架構

image

  1. DispatcherServlet(前端控制器):是整體流程控制的中心,由其調用其它組件處理用戶的請求,有效降低了組件間的耦合性。
  2. HandlerMapping(處理器映射器):負責根據用戶請求找到對應具體的 Handler 處理器。
  3. Handler(處理器):業務處理的核心類,通常由開發者編寫,描述具體的業務。
  4. HandlAdapter(處理器適配器):通過它對處理器進行執行。
  5. View Resolver(視圖解析器):將處理結果生成 View 視圖。
  6. 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 。

注意
image

實現示例

  1. 使用注解形式,將 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();;
    }
}
  1. 替換 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 錯。
    image

對象類型傳參

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 注解進行區分。

復雜對象類型

當對象中出現對象屬性時,則要求入參名稱與對象層次結構名稱保持一致。

image

對象集合

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 接口實現。

image

image

標量轉換器

  • 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)

通常,展示頁面的保存位置比較固定且結構相似,因此可以設定通用的訪問路徑,來簡化頁面配置。

image

示例

<!-- 設定頁面加載的前綴后綴,僅適用於默認形式,不適用於手工標注轉發或重定向的方式 -->
<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";
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM