Spring MVC (spring-webmvc) 使用ガイド

MVC パターンと Spring MVC の概要

MVC : Web アプリケーションのプレゼンテーション層を設計および作成するためのパターンであり、その主な機能はビュー表示をビジネス制御コードから分離することです

MVC は 3 つの役割を使用してさまざまな機能を処理します。

  • モデル(model): データモデル(カプセル化オブジェクト)

  • ビュー (view): データ (html、jsp) の表示を担当します。

  • コントローラー (コントローラー): プログラムのビジネス ロジック処理、スケジューリングを担当します。


MVC アーキテクチャと 3 層アーキテクチャの関係は次のとおりです。

  • MVC は、3 層アーキテクチャのプレゼンテーション層をコントローラー、ビュー、モデルに分割します。
  • 3 層アーキテクチャの目的は分離であり、MVC の目的は Web システムの責任分担を実現することです。

3 層アーキテクチャにおける MVC アーキテクチャの位置図は次のとおりです。

ここに画像の説明を挿入


Spring MVC の概要

SpringMVC は Spring 製品による MVC パターンの特定の実装であり、軽量の WEB フレームワークに属します。これにより、インターフェイスを実装せずに、一連の単純なアノテーションを介して、通常の Java クラスがコントローラーになることができます。RestFul スタイルのプログラミング スタイルもサポートしています。

SpringMVC の機能は、リクエストパラメータの解析と処理、リクエスト結果のカプセル化と返却など、元のサーブレットに共通する機能をカプセル化することです。

SpringMVC は Spring Framework (Spring Framework) のサブモジュールであり、コンテナ (Spring アノテーションをサポート) の概念もあります。


Spring MVC エントリ ケース (xml)

SpringMVC の依存関係

  <dependencies>
    <!--springmvc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.1.6.RELEASE</version>
    </dependency>
    <!--前端控制器 servlet-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
    </dependency>
  </dependencies>

SpringMVC アノテーションのサポートを有効にする

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 包扫描 -->
    <context:component-scan base-package="cn.test"></context:component-scan>
    
    <!-- 配置springmvc的注解驱动。内置了处理器映射器和处理器适配器 -->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 视图解析器 -->
    <!-- 
		 配置返回页面的前缀和后缀。当需要返回一个视图的时候,只需写视图的名称,视图解析器会自动在该名称上拼接前后缀。
         	前缀 + 控制器返回值  + 后缀
         	/WEB-INF/jsps/ + 控制器返回值 + .jsp
    -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsps/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

web.xmlでフロントコントローラーを設定する

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<!-- 配置SpringMVC的前端控制器 DispatcherServlet -->
	<servlet>
		<servlet-name>mvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!--自动加载Springmvc的配置文件-->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>mvc</servlet-name>
		<!-- 处理所有请求,不处理.jsp为后缀的请求 -->
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

コントローラー

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

/**
 * 控制器:需要交给容器管理
 *    方法:接受请求,调用service,完成响应和页面跳转
 */
@Controller
public class HelloController {
    
    

    /**
     * 控制器方法:
     *     接受请求,调用service,完成响应和页面跳转
     *     1、返回值String (跳转的页面路径)
     *     2、需要在方法上通过注解@RequestMapping配置进入此方法的url
     *
     */
    @RequestMapping(value="/hello")
    public String hello() {
    
    
        System.out.println("hello heima23");
        return "success";   //    /WEB-INF/jsps/ + 控制器返回值 + .jsp
    }
}

Spring MVC の原則

Webプロジェクトの実行プロセス

ここに画像の説明を挿入

  1. ブラウザがリクエストを行うhttp://localhost/hello
  2. Tomcat はリクエストを受信し、リクエストを解析して、Request オブジェクトと Response オブジェクトをカプセル化し、それらをアプリケーションに転送します。
  3. 構成された DispatcherServlet は、要求されたパスをインターセプトします。
  4. いくつかの分析と処理の後、DispatcherServlet はリクエストをカスタム コントローラー (@RequestMapping) に転送します。
  5. コントローラーが処理され、リターン パスが与えられます
  6. DispatcherServlet はこのパスを取得し、ビューのレンダリングに対応する JSP を見つけます。

Spring MVCの実行フロー

ここに画像の説明を挿入

  1. ユーザーはブラウザを通じて DispatcherServlet にリクエストを送信します。
  2. DispatcherServlet が HandlerMapping を呼び出すリクエストを受信します
  3. HandlerMapping は特定のプロセッサ チェーンを見つけて DispatcherServlet に返します。
  4. DispatcherServlet は、返されたプロセッサ チェーンに従って HandlerAdapter を呼び出します。
  5. HandlerAdapter は、特定のハンドラー (コントローラー) を呼び出すように適合されています。
  6. コントローラーの実行が完了し、実行結果を返す
  7. HandlerAdapter は、Handler の結果 ModelAndView オブジェクトを DispatcherServlet に返します。
  8. DispatcherServlet は ModelAndView オブジェクトを ViewReslover に渡します
  9. ViewResolver は解析後に特定の View を取得し、DispatcherServlet に返します。
  10. DispatcherServlet は、ビューに従ってビューをレンダリングします (つまり、モデル データをビューに埋め込みます)。
  11. DispatcherServlet はレンダリングされたビューをブラウザーに応答します

Spring MVC の 4 つの主要コンポーネント

ここに画像の説明を挿入

  • フロントコントローラー(DispatcherServlet):

    SpringMVC のコアコンポーネント (DispathcherServlet) は、すべてのコンポーネントの動作を調整します。

  • プロセッサ マッパー(HandlerMapping):

    URL リクエストに従って、対応するプロセッサ (コントローラー内のメソッド) を見つける責任を負います。

  • プロセッサーアダプター(HandlerAdapter):

    統合アダプター インターフェイスはプロセッサをカプセル化し、均一に呼び出すことができます。実際に処理メソッドを呼び出す(Controller内でメソッドを実行)

  • ビューリゾルバー(ViewReslover):

    論理ビューを実際の物理ビューに一致させる

    物理ビュー: JSP ページのフルパス


Spring MVCのリクエストとレスポンスにおけるコンポーネントの実行順序

ここに画像の説明を挿入


コントローラー層

マッピングリクエスト

@RequestMapping アノテーション

@RequestMapping : リクエスト URL と処理メソッドの間のマッピング関係を確立するために使用され、その属性を通じてリクエストにさまざまな制限を設けることもできます

クラスとメソッドでマークできます。クラスで使用すると、リクエストに応答するクラス内のすべてのメソッドがこのアドレスを親パスとして使用することを意味します。

属性:

  • value / path 属性: マッピングのリクエスト アドレスを指定します。指定されたアドレスは URI テンプレート モードにすることができます
  • Method 属性: リクエストのメソッド タイプ (GET、POST、PUT、DELETE など) を指定します。例: RequestMethod.post
  • params 属性: リクエストに含める必要があるパラメータを指定します。リクエストに指定されたパラメータが含まれていない場合、例外がスローされます。
  • headers 属性: メソッドがリクエストを処理するには、リクエストに特定の指定されたヘッダー値が含まれている必要があることを指定します。
  • Consumers 属性: application/json、text/html など、リクエストを処理するために送信されたコンテンツ タイプ (Content-Type) を指定します。
  • 属性を生成します: 返されるコンテンツ タイプを指定し、リクエスト リクエスト ヘッダーの (Accept) タイプに指定されたタイプが含まれる場合にのみ返します。

@GetMapping、@PostMappingなどのアノテーション

@GetMapping、@PostMapping、@PutMapping、@DeleteMapping などのアノテーション。

  • Spring MVC アノテーション @RequestMapping(method = RequestMethod.GET/POST/PUT/DELETE…) の略称
  • HTTP を特定の処理メソッドにマッピングし、一般的な HTTP メソッドのマッピングを簡素化し、アノテーション付きメソッドのセマンティクスをより適切に表現するために使用されます。

リクエストパラメータの受信と処理

リクエストパラメータの受信

SpringMVC では複数の型を使用して、フロントエンドから渡されるアドレスバーパラメータを受け取ることができます

  • 単純型(8 つの基本型 \ 基本 8 型のラッパー型 \ 文字列)

    使用方法: フロントエンドによって渡されるパラメータ名がメソッドの正式なパラメータ名と一致していることを確認するだけで済みます。

    //处理器中属性名必须和请求参数名一致
    @RequestMapping("/simpleParam")
    public String simpleParam(Integer id, String name){
          
          
        System.out.println(id);
        System.out.println(name);
        return "success";
    }
    
  • オブジェクト (pojo) タイプ

    使用方法: フロントエンドによって渡されるパラメーター名が pojo 属性名 (set メソッド) と一致していることを確認するだけで済み、すべてのリクエスト パラメーターが Java オブジェクトに自動的にカプセル化されます。

    @RequestMapping("/dtoParam")
    public String voParam(UserDTO dto){
          
          
        System.out.println(dto);
        return "success";
    }
    
  • 配列型

    使用方法: フロントエンドによって渡されるパラメータ名がメソッド内の配列パラメータ名と一致していることを確認するだけで済みます。

    同名のパラメータが渡され、リクエストパラメータは自動的に配列にカプセル化されます。

  • コレクションタイプ

    コレクションをオブジェクトにラップするだけで、フロントエンドから渡されたデータがオブジェクトのコレクション プロパティに自動的にカプセル化されます。

  • 日付型

    Spring MVC には一連の型コンバーターが組み込まれており、リクエストパラメーターの String 型を特定の形式 (例: Integer) に自動的に変換できます。

    一部の一般的な型については、Spring MVC に型コンバーターが組み込まれていますが、より柔軟な形式 (日付と時刻) を持つ一部のパラメーターの場合、Spring MVC は型変換を完了できないため、カスタム型コンバーターが必要です


リクエストパラメータの処理

@RequestParam アノテーション

コントローラー メソッドのパラメーターの前に注釈が付けられ、リクエスト内の URL によって渡される共通パラメーターにいくつかの制限を加えるために使用され、次の 3 つの属性がサポートされます。

  • value / name属性: リクエストによって渡されたパラメータ名をバインドするために使用されるデフォルトの属性。通常、リクエストパラメータがコントローラメソッドの入力パラメータと矛盾する場合に使用されます。
  • required属性: このパラメータを渡す必要があるかどうかを指定するために使用されます
    • @RequestParam によって変更されたパラメータはデフォルトで値を渡す必要があり、required = false を使用してオプションの値を指定できます。
  • defaultValue属性: パラメータのデフォルト値を指定します (パラメータが必須ではなく、リクエストがパラメータを渡さない場合は、デフォルト値が使用されます)
@RequestMapping("/list1")
public String test1(int userId) {
    
    
  return "list";
}
@RequestMapping("/list2")
public String test2(@RequestParam int userId) {
    
    
  return "list";
}

@RequestParam アノテーションなしの場合:

  • フロントエンド パラメーター名を有効にするには、バックエンド コントローラーの変数名と一致している必要があります。
  • パラメータはオプションです

リクエストヘッダー情報を受け入れる

コントローラーで現在のリクエストのリクエストヘッダーを取得する方法:

  • @RequestHeaderアノテーションはメソッドのパラメーターに設定されます。フロント コントローラーはヘッダー情報を自動的に取得します。
    •  @RequestHeader Map map : 获取所有的请求头
      
    •  @RequestHeader("cookie") String cookie : 根据key从所有头信息中获取指定头信息
      
  • @CookieValue("key") : キーに従ってCookieから指定された値のデータを取得します
  	/**
     * 在控制器中获取,当前请求的请求头
     */
    @RequestMapping(value="/demo12")
    public String demo12(@RequestHeader Map map,
                         @RequestHeader("cookie") String cookie,
                         @CookieValue("JSESSIONID") String sessionId) {
    
    
        System.out.println(map);
        System.out.println(cookie);
        System.out.println(sessionId);
        return "success";
    }

ファイルのアップロード

クライアントファイルアップロードの 3 つの要素

  • フォームのメソッド form = post
  • フォーム form の enctype="multipart/form-data"
  • from フォームでの入力のタイプ = file

springmvc のサーバー

  • ファイルアップロードの依存関係

    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>
    
  • SpringMVC設定ファイルでファイルアップロードパーサーを設定する必要があります(アップロードされたコンテンツをMultipartFileオブジェクトに自動的に変換します)

    <!--
        文件解析器
            id:固定值(multipartResolver)
            property:其中指定上传文件的大小规则
    -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--文件的大小规则  5M = 1024 * 1024 * 5 -->
        <property name="maxUploadSize" value="5242880"></property>
    </bean>
    
  • コントローラー メソッドで、MultipartFile オブジェクト パラメーターを直接使用して、アップロードされたファイルをカプセル化します。

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.multipart.MultipartFile;
    import java.io.File;
    import java.io.IOException;
    
    @Controller
    public class FileUploadController {
          
          
    
        /**
         * 上传文件到服务端。服务端将文件转存到E:\file
         *  MultipartFile :封装上传的文件
         *      参数名 :和上传文件的input的name属性一致
         */
        @RequestMapping("/upload")
        public String upload(MultipartFile myFile, String name) throws IOException {
          
          
            System.out.println("name=" + name);
            System.out.println(myFile.getOriginalFilename()); //获取上传文件名
            System.out.println(myFile.getSize()); //获取上传文件大小
    
            File file = new File(new File("E:\\file"), myFile.getOriginalFilename());
            myFile.transferTo(file);  //写入文件内容
    
            return "success";
        }
    }
    

@RequestBody、@ResponseBody アノテーション

Ajax + jsonで非同期対話を実現

ここに画像の説明を挿入

Spring MVC での Ajax データ対話は、2 つのアノテーションによって開発を簡素化できます。

  • @RequestBody : リクエストされた json 文字列を指定された Java オブジェクトに自動的に変換します (リクエストの処理)

  • @ResponseBody : コンバーターを通じて Java オブジェクトを指定された形式 (通常は json 文字列) に自動的に変換し、応答します (応答を処理します)。

    • @RestControllerアノテーション = @ResponseBody + @Controller の組み合わせ
        @RequestMapping("/testAjax")
        @ResponseBody
        public  User testAjax(@RequestBody User user) {
          
          
            System.out.println("ajax请求的数据对象=" + user);
            //调用业务逻辑
            User user2 = new User();
            user2.setUsername("张三");
            return user2;
        }
    
  • @RestControllerアノテーション: @ResponseBody + @Controller の組み合わせ
    • @RestController には @RessponseBody のアノテーション効果が含まれているため、コントローラーのメソッドは jsp または html インターフェイスを返すことができず、設定された InternalResourceViewResolver は機能せず、返されたコンテンツのみを返すことができます。

知らせ:

  • Spring MVC はデフォルトで MappingJackson2HttpMessageConverter を使用して json データを変換します。これは jackson パッケージに追加する必要があります。

        <dependency>
        	<groupId>com.fasterxml.jackson.core</groupId>
        	<artifactId>jackson-databind</artifactId>
        	<version>2.9.8</version>
        </dependency>
    
  • Spring Boot はデフォルトで jackson を統合するため、jackson 関連の依存関係を追加する必要はありません


ページジャンプ

Spring MVC がサーブレットネイティブ API を取得

サーブレット ネイティブ API オブジェクト:

  • HttpServletRequest
  • HttpSevletResponse
  • HTTPセッション

文法規則:

  • 方法 1 (推奨): コントローラー メソッドのメソッド パラメーターとしてオブジェクトを構成します。

    	/**
         * 获取Servlet原生API对象(request,response,session)
         */
        @RequestMapping("/demo2")
        public String demo2(HttpServletRequest request, HttpServletResponse response, 
                            HttpSession session) {
          
          
            request.setAttribute("user", "1");
            System.out.println(request);
            System.out.println(response);
            System.out.println(session);
            return "success";
        }
    
  • 方法 2: @Autowired を通じて必要な API オブジェクトを挿入する


ページジャンプの転送

リクエスト転送: データ損失なしでリクエストを 1 つだけ送信します (SpringMVC のデフォルトのページ ジャンプ フォーム)

  • 方法 1: 論理ビューに直接戻る

    • 基礎となるリクエストはビュー パーサーを介して転送され、プレフィックスとサフィックスが追加されて物理ビュー (ページの完了パス) が形成され、レンダリングとジャンプが行われます。
  • 方法 2: 転送から転送への使用

    • 構文規則 (戻り値): forward: 物理ビュー
    • forward: キーワードの後のパスは、ビュー リゾルバーを経由しないことを示します。
        @RequestMapping("/demo3")
        public String demo3() {
          
          
            System.out.println("forward转发");
            return "forward:/WEB-INF/jsps/success.jsp";
        }
    
  • 方法 3: サーブレット ネイティブ API を使用する

    • 注: コントローラーメソッドの戻り値: void
    	@RequestMapping("/demo3")
        public void demo3(HttpServletRequest request, HttpServletResponse response) throws Exception {
          
          
            System.out.println("servlet原生API对象");
            request.getRequestDispatcher("/WEB-INF/jsps/success.jsp").forward(request, response);
        }
    

転送要求時にデータを運ぶ

  • 転送時にデータを運びます。応答データを返します。

  • 方法 1 (推奨): データをリクエスト フィールドにバインドする

    	@RequestMapping("/demo4")
        public String demo4(HttpServletRequest request){
          
          
            // 将数据绑定到request域
            request.setAttribute("username", "张三")
            return "result"
        }
    

    ページは el 式を通じて応答データを取得し、それを表示します。

  • 方法 2: Model オブジェクトにバインドする

    モデル: SpringMVC のモデルはパラメーターに基づいて構成され、基礎となる層はリクエストを通じて実装されます。データ応答を完了するためのリクエストを置き換えるために使用できます。

    	@RequestMapping("/demo4")
        public String demo4(Model model){
          
          
            // 将数据绑定到Model对象
            model.addAttribute("username", "张三")
            return "result"
        }
    
  • 方法 3 (公式): ModelAndView 経由で返す

    ModelAndView : 返されたビュー アドレスとデータ バインディングを指定できるモデル ビュー オブジェクト

    文法規則:

    • メソッドの戻り値: ModelAndView
    • メソッド内ではModelAndViewのsetViewNameメソッドでジャンプ先のページを指定します。
    • メソッドでは、ModelAndView の addObject メソッドを通じてリクエスト フィールドに格納する必要があるデータを指定します。
    	@RequestMapping("/demo4")
        public ModelAndView demo4() {
          
          
            ModelAndView mv = new ModelAndView();
            // 指定响应数据
            mv.addObject("username", "传智播客");
            // 配置返回页面视图地址
            mv.setViewName("result"); 	// 支持逻辑视图,支持forward:物理视图
            return mv;
        }
    

ページジャンプのリダイレクト

リダイレクト: さまざまな方法を通じて、さまざまなネットワーク要求を他の場所にリダイレクトします (Web ページのリダイレクト、ドメイン名のリダイレクト、ルート選択の変更も、データ パケットがルーティングされるパスのリダイレクトです)。

実装原則:

  • クライアント ブラウザは http リクエストを送信し、Web サーバーはリクエストを受信した後、302 ステータス コード応答と対応する新しい場所をクライアントに送信します。クライアントは、それが 302 リクエストであることを認識すると、自動的に新しい http リクエストを送信します。要求された URL は新しい場所であり、サーバーは新しい http リクエストに従ってクライアントに応答します。

  • ここでの場所は任意の URL に定義できます。ブラウザはリクエストを再送信するため、リクエスト配信の概念はありません。リダイレクトされたパスはクライアント ブラウザのパス バーに表示され、クライアントはパスの変更を監視できます。

特徴:

  • それはクライアントの行動です
  • 少なくとも 2 回のアクセス要求を行ったブラウザである
  • ブラウザのアドレスが変わります
  • 2 つのジャンプ間で送信されたデータ (リクエスト範囲) が失われます。つまり、リダイレクトされたページからフォームの値を取得できません。
  • 任意の URL にリダイレクトできます

リダイレクトする方法:

  • 方法 1 (推奨): リダイレクトを使用してリダイレクトします

        @RequestMapping("/demo5")
        public void demo5(HttpServletRequest request, HttpServletResponse response) throws IOException {
          
          
            System.out.println("第一次请求");
            return "redirect:/demo6";
        }
    
    	@RequestMapping("/demo6")
        public String demo6() {
          
          
            System.out.println("重定向到demo6");
            return "success";
        }
    
  • 方法 2: サーブレット ネイティブ API を使用する

        @RequestMapping("/demo5")
        public void demo5(HttpServletRequest request, HttpServletResponse response) throws IOException {
          
          
            System.out.println("第一次请求");
            response.sendRedirect("/demo6");
        }
    
    	@RequestMapping("/demo6")
        public String demo6() {
          
          
            System.out.println("重定向到demo6");
            return "success";
        }
    

Spring MVCはセッションドメインを操作します

従来の方法でセッション ドメインを操作する

@RequestMapping("/hello13.action")
public String hello13(HttpSession session){
    
    
    session.setAttribute("prod", "电视机");
    return "hello";
}

@RequestMapping("/hello14.action")
public String hello14(HttpSession session){
    
    
    String prod = (String) session.getAttribute("prod");
    System.out.println(prod);
    return "hello";
}

@SessionAttribute("name") を使用して、名前に従ってセッションから対応するパラメーターの値を取得します。

@GetMapping("/test-mvc-get-session")
public String testMvcGetSession(@SessionAttribute("girl") String girl) {
    
    
    System.out.println("testMvcGetSession -----> girl in session is " + girl);
    return "success";
}

ModelMap オブジェクトを使用してセッション フィールドから値を取得します。

@RequestMapping("/getValue")
public String getValue(ModelMap modelMap){
    
    
    System.out.println(modelMap.get("value"));
    return "success";
}

セッションフィールドをクリアします

@RequestMapping("/delValue")
public String delValue(SessionStatus sessionStatus){
    
    
    //清空session
    sessionStatus.setComplete();
    return "success";
}


静的リソースを解放します (処理のために Spring MVC に渡されません)

jquery.js など、ロードする必要がある静的リソースがある場合、jquery.js にロードされない理由は、Google Developer Tools を通じてパッケージをキャプチャすることでわかります。

  • Spring MVC のフロントエンド コントローラー DispatcherServlet の URL パターン設定は / (デフォルト) です。これは、一部の静的ファイル (js、html、css、jpg など) を含む、jsp リクエストを除くすべてのリクエストがインターセプトされることを意味します。

静的リソースを解放する方法

  • 方法 1 (推奨): Springmvc 設定ファイルですべての静的リソース ファイルを均一に設定および解放する

    • SpringMVC が静的リソースを処理する場合、デフォルトのサーブレットに処理を委譲します。
    • デフォルトのサーブレット: Tomcat のデフォルトのサーブレット
    <mvc:default-servlet-handler/>
    
  • 方法 2: SpringMVC 設定ファイルで静的リソースのリリースを設定する

    • mvc:リソースタグ
      • マッピング タグ: リクエスト パスの URL マッピング ルール
      • location タグ: 静的リソースの物理ディレクトリ

    SpringMVCのフロントコントローラに静的リソースを要求した場合、リソース解放の設定に従って

    1. 特定のコントローラー処理を探す必要がなくなりました
    2. ロケーションパスから一致するリソースを検索します
        <mvc:resources mapping="/js/*" location="/js/"></mvc:resources>
        <mvc:resources mapping="/image/*" location="/image/"></mvc:resources>
        <mvc:resources mapping="/css/*" location="/css/"></mvc:resources>
    
  • 方法 3:web.xmlフロントエンド コントローラーの URL マッピング ルールを変更し、特殊な文字列で終わるリクエストがフロントエンド コントローラーに渡されて処理されます。

    • サーブレットマッピングタグ
      • URLパターンタグ:
        • /* : すべてのリクエスト (JSP ページを含む) に有効
        • / : すべてのリクエストに有効 (JSP ページを除く)
    • SpringMVC に入る必要があるすべてのリクエストは .do で終わる必要があります
    • コントローラー メソッドでは、@RequestMapping で追加の構成を行う必要はありません。
        <servlet-mapping>
            <servlet-name>mvc</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
    

Spring MVC のグローバル データ処理 (@ControllerAdvice)

@ControllerAdvice : コントローラー層のグローバルデータ処理クラスを定義します。@RequestMapping アノテーションが付けられたコントローラー メソッドに作用します。

スキャン可能な注釈 @Component が含まれています

通常、次の注釈とともに使用されます。

  • @ExceptionHandler (例外処理)
  • @ModelAttribute (データ バインディング)
  • @InitBinder (データ前処理)
  • **注意:** これら 3 つのアノテーションは通常のコントローラー クラスで使用でき、ControllerAdvice にはカスタマイズできるスコープのみがあります (すべてデフォルト)

@ControllerAdvice は次の属性をサポートします。

  • value /basePackages 属性: 1 つ以上のパッケージを指定する配列タイプ。使用できる基本パッケージを指定するために使用されます。

    指定されたパッケージの下のコントローラーとそのサブパッケージの下のコントローラーに作用します。

    指定しない場合、デフォルトでスキャンされたすべてのパッケージが使用されます。

  • basePackageClasses 属性: これは、basePackages のバリアントである配列タイプで、1 つ以上のコントローラー クラスを指定します。これらのクラスのパッケージおよびサブパッケージの下にあるすべてのコントローラーは、この @ControllerAdvice によって管理されます。

  • assignableTypes 属性: 配列タイプ。特定のコントローラー タイプを指定するために使用されます。共通のインターフェイスや親クラスなどにすることができます。

  • annotations 属性: 1 つ以上の注釈を指定します。これらの注釈によってマークされたコントローラーは @ControllerAdvice によって管理されます。


例外処理 (@ExceptionHandler)

例外を処理するには、通常、次の 2 つの方法があります。

  • 1 つは現在のメソッド処理 (try-catch) で、ビジネス コードと例外処理コードの結合が発生します。

  • 1 つは、現在のメソッドがそれを処理せず、例外の発生後に処理のために呼び出し元に直接スローすることです。

    Spring フレームワークを使用すると、コードは最終的にフレームワークによって呼び出されます。つまり、例外は最終的にフレームワークにスローされ、フレームワークは例外を均一に処理する例外ハンドラーを指定します。


方法 1: @ControllerAdvice および @ExceptionHandler アノテーションを使用してグローバル例外処理を定義する

使い方:

  • @ControllerAdvice : グローバル処理クラス、例外監視を定義します。Javaクラスの標準
  • 例外処理メソッドを定義する
    • 戻り値 文字列 (ビュー)
    • パラメータ: モデル
    • @ExceptionHandler アノテーション: メソッドにマークされています
      • value 属性: 現在の例外ハンドラーによって処理される例外タイプを指定します。
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * 定义全局异常处理
 */
@ControllerAdvice
public class MyHandlerException2 {
    
    
    
    // @Validated参数校验 ,解析BindingResult的错误信息并返回
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public JsonResult exceptionHandler(BindException e, BindingResult result) {
    
    
        List<FieldError> fieldErrors = result.getFieldErrors();
        String collect = fieldErrors.stream()
            .map(f -> f.getField()+":"+f.getDefaultMessage())
            .collect(Collectors.joining(","));
        return new JsonResult(JsonResult.Validated_ERROR, collect);
    }

    @ExceptionHandler(value=Exception.class)
    public String handlerException(Model model) {
    
    
        model.addAttribute("errorMsg", "运行报错!");
        return "forward:error.jsp";
    }
}

方法 2: カスタム例外ハンドラー

クラスをカスタマイズして HandlerExceptionResolver インターフェースを実装し、resolveException メソッドを書き換えて、管理のために例外ハンドラーを Spring コンテナーに渡します。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义异常处理器
 * 跳转到一个美化的页面,携带错误信息
 */
@Component
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
    
    
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
    
    
        ModelAndView mv = new ModelAndView();
        mv.addObject("errorMsg","运行报错!");
        mv.setViewName("forward:error.jsp");
        return mv;
    }
}

方法 3: Web によって提供される例外メカニズムを使用する

web.xml で例外処理設定を提供します

<!--处理403异常-->
<error-page>
    <error-code>403</error-code>
    <location>/403.jsp</location>
</error-page>
<!--处理404异常-->
<error-page>
    <error-code>404</error-code>
    <location>/404.jsp</location>
</error-page>

データ バインディング (@ModelAttribute)

グローバル データ バインディング関数を使用して、いくつかの初期データ操作を行うことができます。たとえば、一部のパブリック データを @ControllerAdvice アノテーションが付けられたクラスで定義できるため、これらのデータはすべてのコントローラー インターフェイスでアクセスできます。

@ModelAttribute アノテーションでマークされたメソッドは、ターゲットのコントローラー メソッドを実行する前に実行され、グローバル @RequestMapping がここで設定されたキーと値のペアを取得できるようにするために、@ControllerAdvice と組み合わせてよく使用されます。

@ModelAttribute アノテーションでマークされたメソッドの戻りデータはグローバル データです。デフォルトでは、このグローバル データのキーは返されたデータ型で、値はメソッドの戻り値です。もちろん、開発者は @ModelAttribute アノテーションの name 属性を使用してキーを再指定できます。

	// 无返回值方法,不指定@ModelAttribute的name属性
	// 键值对直接放入Model中,可以自定义key,value
    @ModelAttribute()
    public void presetParam(Model model) {
    
    
        model.addAttribute("globalAttr", "我是全局参数");
    }

    // 有返回值方法,不指定 @ModelAttribute 的 name 属性
	// 返回值是Map类型,绑定的全局数据键值对的 key 就是 "map",value 为方法的返回值
    @ModelAttribute()
    public Map<String, String> presetParam2() {
    
    
        Map<String, String> map1 = new HashMap<String, String>();
        map1.put("key1", "value1");
        return map1;
    }

	// 有返回值方法,指定 @ModelAttribute 的 name 属性
    // 绑定的全局数据键值对的 key 就是 name 属性的值,value 为方法的返回值
    @ModelAttribute(name = "map2")
    public Map<String, String> presetParam3() {
    
    
        Map<String, String> map = new HashMap<String, String>();
        map.put("key2", "value2");
        return map;
    }

	// 接受请求参数
    @ModelAttribute()
    public void presetParam4(@RequestParam("name") String name,Model model) {
    
    
        model.addAttribute("name", name);
    }

使用

	 //1.使用Model取出
    @GetMapping("model")
    public String methodOne(Model model) {
    
    
        Map<String, Object> modelMap = model.asMap();
        System.out.println(modelMap.get("name").toString()); // 传入name的值    
        return modelMap.get("globalAttr").toString();
    }

    //2.使用ModelMap取出
    @GetMapping("modelMap")
    public String methodThree(ModelMap modelMap) {
    
    
        return modelMap.get("map").toString();
    }

    //3.@ModelAttribute()指定key,直接取出
    @GetMapping("modelAttribute")
    public String methodTwo(@ModelAttribute("map2") Map map2) {
    
    
        return map2.toString();
    }

データの前処理 (@InitBinder)

参考:https://blog.csdn.net/wang0907/article/details/108357696

@InitBinderアノテーション: リクエスト データの前処理。WebDataBinder の設定に使用され、フロントエンド リクエスト パラメーターをモデルに自動的にバインドするために使用されます。

WebDataBinderの一般的なメソッドは次のとおりです。

// 设置字段默认前缀,可用于绑定同属性多对象
public void setFieldDefaultPrefix(String fieldDefaultPrefix)

// 设置无法被接受的字段
public void setDisallowedFields(String... disallowedFields)
    
// 注册自定义编辑器
public void registerCustomEditor(Class<?> var1, PropertyEditor var2)

// 注册校验器
public void addValidators(Validator... validators)

複数のオブジェクトを同じプロパティでバインドする

public class TestController{
    
    
    @RequestMapping("/test")
    public String test(User user, Person person){
    
    
        System.out.println(user, person);
        return "success"
    }
    
	@InitBinder("user")
    public void initBinderUser(WebDataBinder dataBinder){
    
    
        dataBinder.setFieldDefaultPrefix("u.");
    }

    @InitBinder("person")
    public void initBinderPerson(WebDataBinder dataBinder){
    
    
        dataBinder.setFieldDefaultPrefix("p.");
    }
}

赋试url:http://localhost:8080/test?u.name=aaa&p.name=bbb


プロパティエディターを登録する

パラメータを受け取る場合、String型やInt型など基本的なデータ型であればSpringMVCで直接処理できますが、それ以外の複雑なオブジェクト型の場合は処理できない場合があり、その際の処理には属性エディタが必要になります(ソースデータはString)。通常はString→属性エディタ→ターゲット型の処理となります。

Spring では、org.springframework.beans.propertyeditors.CustomDateEditor など、いくつかのデフォルトのプロパティ エディタが提供されています。また、java.beans.PropertyEditorSuppotr を継承することで、特定のビジネスに応じてプロパティ エディタをカスタマイズすることもできます。

  • デフォルトのプロパティエディタを使用する

    	@InitBinder
        public void initBinder(WebDataBinder dataBinder){
          
          
            /*
             * 创建一个字符串微调编辑器
             * 参数{boolean emptyAsNull}: 是否把空字符串("")视为 null
             */
            StringTrimmerEditor trimmerEditor = new StringTrimmerEditor(true);
            /*
             * 注册自定义编辑器
             * 接受两个参数{Class<?> requiredType, PropertyEditor propertyEditor}
             * requiredType:所需处理的类型
             * propertyEditor:属性编辑器,StringTrimmerEditor就是 propertyEditor的一个子类
             */
            dataBinder.registerCustomEditor(String.class, trimmerEditor);
            //日期格式的字符串转换成Date对象
            dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), false));
        }
    
  • カスタムプロパティエディター

        /**
         * @description:  防止xss注入
         * @params:  String类型转换,将所有传递进来的String进行HTML编码,防止XSS攻击
         */
        @InitBinder
        protected void initBinder2(WebDataBinder binder) {
          
          
    
            System.out.println("22222222222222");
    
            //匿名类,自定义属性编辑器 PropertyEditorSupport
            binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
          
          
                @Override
                public void setAsText(String text) {
          
          
                    setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
                }
                @Override
                public String getAsText() {
          
          
                    Object value = getValue();
                    return value != null ? value.toString() : "";
                }
            });
        }
    

登録バリデーター

  • カスタムバリデーター

    org.springframework.validation.Validator を直接実装すると、インターフェイスには次の 2 つのメソッドしかありません。

    • 1 つは、検証がサポートされているかどうかを確認するための support(Class<?> clazz) メソッドです。
    • 1 つは、特定の検証を行うための validate(Object target, Errorserrors) メソッドです。
    /**
     * 定义一个校验器
     * 该校验器校验用户录入的userName长度是否大于8,并给出响应的错误信息,
     * 错误信息直接设置到errors中,最终会设置到org.springframework.validation.BindingReuslt,
     * 在接口中直接定义该对象则会自动注入对象值,从而可以获取到对应的错误信息。
     */
    @Component
    public class UserValidator implements Validator {
          
          
    
    	@Override
    	public boolean supports(Class<?> clazz) {
          
          
    		// 只支持User类型对象的校验
    		return User.class.equals(clazz);
    	}
    
    	@Override
    	public void validate(Object target, Errors errors) {
          
          
    		User user = (User) target;
    		String userName = user.getUserName();
    		if (StringUtils.isEmpty(userName) || userName.length() < 8) {
          
          
    			errors.rejectValue("userName", "valid.userNameLen",
    					new Object[] {
          
           "minLength", 8 }, "用户名不能少于{1}位");
    		}
    	}
    }
    
    	@Autowired
    	private UserValidator userValidator;
    
        // 注册校验器
    	@InitBinder
    	private void initBinder(WebDataBinder binder) {
          
          
    		binder.addValidators(userValidator);
    	}
    

Spring MVC インターセプター

Interceptor は Spring MVC が提供する技術で、Filter と同様の機能を持ち、Controller に入る前、Controller を出た後、ページのレンダリング後にリクエストをインターセプトすることができます。

ここに画像の説明を挿入

インターセプターとフィルターの違い

  • フィルタはサーブレット仕様の一部であり、任意の Java Web プロジェクトで使用できます。

    インターセプターは Spring MVC フレームワークに属しており、Spring MVC フレームワークを使用するプロジェクトのみが使用できます。

  • URL パターンで /* を使用してフィルターを構成すると、アクセスされるすべてのリソースをインターセプトできます

    インターセプターは、アクセスされたコントローラー メソッドのみをインターセプトします。アクセスが jsp、js、html、css、画像、その他のリソースの場合はインターセプトしません。


HnadlerInterceptor インターフェイス メソッドを実装する

  • HnadlerInterceptor インターフェースを実装する

  • 3 つのメソッド (3 つのインターセプト ポイント) を実装します。

    // 进入controller方法之前执行的内容(对请求拦截处理)
    	// 返回值 boolean。true :放行(继续向后执行,进入到controller),false :拦截过滤
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
    
    // 执行了controller方法之后,执行的内容(对象响应进行拦截处理)
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                           Object handler, ModelAndView modelAndView)
    
    // 页面渲染完成之后,执行(一般不用)
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                                Object handler, Exception ex)
    

URL実装に基づくインターセプター

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义拦截器
 * 实现HnadlerInterceptor接口。实现其中的三个方法(三个拦截点)
 */
public class MyInterceptor01 implements HandlerInterceptor {
    
    

    /**
     * 进入controller方法之前执行的内容(对请求拦截处理)
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        String path = request.getServletPath();
        if (path.matches(Const.NO_INTERCEPTOR_PATH)) {
    
    
        	//不需要的拦截直接过
            return true;
        } else {
    
    
        	// 这写你拦截需要干的事儿,比如取缓存,SESSION,权限判断等
            System.out.println("====================================");
            return true;
        }
    }

    /**
     * 执行了controller方法之后,执行的内容(对象响应进行拦截处理)
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
    
        System.out.println("执行MyInterceptor01的postHandle方法");
    }

    /**
     * 页面渲染完成之后,执行(不用)
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
    
        System.out.println("执行MyInterceptor01的afterCompletion方法");
    }
}

キーコード: path.matches(Const.NO_INTERCEPTOR_PATH は正規一致に基づく URL

/**
 * 常量类
 */
public class Const {
    
    

    public static final String SUCCESS = "SUCCESS";
    public static final String ERROR = "ERROR";
    public static final String FIALL = "FIALL";
    /**********************对象和个体****************************/
    public static final String SESSION_USER = "loginedAgent"; // 用户对象
    public static final String SESSION_LOGINID = "sessionLoginID"; // 登录ID
    public static final String SESSION_USERID = "sessionUserID"; // 当前用户对象ID编号

    public static final String SESSION_USERNAME = "sessionUserName"; // 当前用户对象ID编号
    public static final Integer PAGE = 10; // 默认分页数
    public static final String SESSION_URL = "sessionUrl"; // 被记录的url
    public static final String SESSION_SECURITY_CODE = "sessionVerifyCode"; // 登录页验证码
    // 时间 缓存时间
    public static final int TIMEOUT = 1800;// 秒
	public static final String ON_LOGIN = "/logout.htm";
	public static final String LOGIN_OUT = "/toLogout";
    // 不验证URL anon:不验证/authc:受控制的
    public static final String NO_INTERCEPTOR_PATH =".*/((.css)|(.js)|(images)|(login)|(anon)).*";
}

HandlerInterceptorAdapter クラスのメソッドを継承する

注: HandlerInterceptorAdapter クラスを継承するメソッドは古いです

1. 注釈を作成します。

/**
 * 在需要登录验证的Controller的方法上使用此注解
 */
@Target({
    
    ElementType.METHOD})	// 可用在方法名上
@Retention(RetentionPolicy.RUNTIME)	// 运行时有效
public @interface LoginRequired {
    
    
	
}

2. インターセプターを作成します。

public class MyInterceptor02 extends HandlerInterceptorAdapter{
    
    
	
	 @Override
	 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
	 	// 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
    
    
            return true;
        }
        // 方法注解级拦截器
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        // 判断接口是否需要登录
        LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);
        // 有 @LoginRequired 注解,需要认证
        if (methodAnnotation != null) {
    
    
            // 拦截需要干的事儿,比如取缓存,SESSION,权限判断等
            System.out.println("====================================");
            return true;
        }
        return true;
	}
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
    
        logger.info("进入到拦截器中:postHandle() 方法中");
        System.out.println(request.getRequestURI());
    }
 
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
    
        logger.info("进入到拦截器中:afterCompletion() 方法中");
        System.out.println(request.getServletPath());
    }
}

レジスタインターセプタ

  • 構成クラス

    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import com.*.*.interceptor.AdminInterceptor;
    
    /**
     * 拦截器配置
     */
    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
          
          
        
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
          
          
            //注册MyInterceptor01拦截器
            InterceptorRegistration registration = registry.addInterceptor(getMyInterceptor01());
            registration.addPathPatterns("/**");                      //所有路径都被拦截
            registration.excludePathPatterns(                         //添加不拦截路径
                                             "登陆路径",            	//登录
                                             "/**/*.html",            //html静态资源
                                             "/**/*.js",              //js静态资源
                                             "/**/*.css",             //css静态资源
                                             "/**/*.woff",
                                             "/**/*.ttf"
                                             );    
        
            // 注册MyInterceptor02拦截器。拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要拦截
            registry.addInterceptor(getMyInterceptor02()).addPathPatterns("/**");
        }
        
        @Bean
    	 public MyInterceptor01 getMyInterceptor01() {
          
          
    		 return new MyInterceptor01();
    	 }
    	 
    	 @Bean
    	 public MyInterceptor02 getMyInterceptor02() {
          
          
    		 return new MyInterceptor02();
    	 }
    }
    
  • XML の方法

    SpringMVC 構成ファイルに、インターセプター構成を追加します (構成インターセプターは、インターセプトする必要がある URL およびメソッド・ルールに対応します)。

        <!--配置SpringMVC的拦截器-->
        <mvc:interceptors>
            <!--配置具体的拦截器和拦截器的拦截规则-->
            <mvc:interceptor>
                <!-- mapping : 配置拦截规则。 /** 表示拦截所有  -->
                <mvc:mapping path="/**"/>
                <!-- exclude-mapping: 配置不拦截的规则 -->
                <mvc:exclude-mapping path="/hello/demo2"/>
                <!--创建对象:在当前拦截器中有效-->
                <bean class="cn.test.interceptors.MyInterceptor01"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    

カスタムインターセプターチェーン

開発中、インターセプターを単独で使用することも、複数のインターセプターを同時に使用してインターセプター チェーンを形成することもできます。

開発手順は、登録時に複数のインターセプタを登録することを除いて、単一のインターセプタの場合と同じですが、ここでの登録の順序はインターセプタの実行順序を表します。

インターセプターの構成: 複数のインターセプター チェーンの実行順序は構成順序に関連します。

    <!--配置SpringMVC的拦截器-->
    <mvc:interceptors>
        <!--配置具体的拦截器和拦截器的拦截规则-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/hello/demo2"/>
            <bean class="cn.test.interceptors.MyInterceptor01"></bean>
        </mvc:interceptor>

        <!--配置具体的拦截器和拦截器的拦截规则-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/hello/demo2"/>
            <bean class="cn.test.interceptors.MyInterceptor02"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

拡大

カスタム型コンバータ

1. 型コンバータをカスタマイズして型変換のメソッドを実装する

import org.springframework.core.convert.converter.Converter;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 自定义的类型转换器
 * 实现Converter接口,<原始类型,目标类型>
 */
public class StringToDateConverter implements Converter<String, Date> {
    
    

    /**
     * 日期转化
     *   参数:请求参数中的原始数据
     *   返回值:转换好的数据(目标类型)
     */
    public Date convert(String source) {
    
    
        Date date = null;
        try {
    
    
            date = new SimpleDateFormat("yyyy-MM-dd").parse(source);
        }catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return date;
    }
}

2. SpringMvcの変換サービスにカスタム型変換を登録し、SpringMVCのアノテーションドライバーにサービスを登録する

  • XML の方法
    <!--将自定义的类型转化器加入Springmvc的转化器ConversionService的集合中-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!--使用集合传入自定义的converter-->
        <property name="converters">
            <set>
                <!--一个bean对应一个类型转换器-->
                <bean class="cn.test.converter.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>

    <!--将Springmvc的转化器注册到springmvc驱动中-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
  • 構成クラス
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.GenericConversionService;

@Configuration
public class ConvertConfig {
    
    
    @Bean
    public ConversionService genericConversionService(GenericConversionService genericConversionService){
    
    
        genericConversionService.addConverter(new StringToDateConverter());
        return genericConversionService;
    }
}

Restful スタイルと @PathVariable アノテーション

Restful は REST と呼ばれ、正式名称は Representational State Transfer です。

REST はソフトウェア アーキテクチャ スタイルであり、HTTP がリソース中心であるべきであることを強調しています (動詞は URL 内にできるだけ出現しないようにする必要があります)。

これは、HTTP リクエストに対する 4 つのアクションを定式化します。これらはそれぞれ、リソースに対する CRUD 操作を表します: GET (取得)、POST (新規)、PUT (更新)、DELETE (削除)

休息の使い方:

  • 同じ URL でも、リクエスト方法が異なると、異なる業務処理が実行されます。
  • カスタム アドレス パラメーター/PATH/{カスタム アドレス パラメーター名}
  • REST形式のリクエストアドレスのプレースホルダの値を受け取る: @PathVariable(value="アドレスパラメータ名") アノテーション
  • リクエストメソッド:GET(取得)、POST(新規)、PUT(更新)、DELETE(削除)
であった 安らかな
保存 /saveUser POST /ユーザー
改訂 /udpateUser?uid=1 PUT /ユーザー/1
消去 /deleteUser?uid=1 /ユーザー/1を削除
クエリを実行する /findUserByUid?uid=1 GET /user/1
すべてをクエリする /findUser GET /ユーザー
@Controller
@RequestMapping("/user")
public class UserController {
    
    

    /**
     * 根据id查询
     *  请求地址:/user/5
     *  请求方式:GET
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String findById(@PathVariable(value="id") String id) {
    
    
        System.out.println("根据id查询,id=" + id);
        return "success";
    }

    /**
     * 根据id删除
     *  请求地址:/user/5
     *  请求方式:DELETE
     */
    @RequestMapping(value="/{id}", method = RequestMethod.DELETE)
    public String delete(@PathVariable(value="id") String id) {
    
    
        System.out.println("根据id删除,id=" + id);
        return "success";
    }

    /**
     * 根据id更新
     *  请求地址:/user/5
     *  请求方式:PUT
     */
    @RequestMapping(value="/{id}", method = RequestMethod.PUT)
    public String update(@PathVariable(value="id") String id) {
    
    
        System.out.println("根据id更新,id=" + id);
        return "success";
    }

    /**
     * 保存
     *  请求地址:/user
     *  请求方式:POST
     */
    @RequestMapping(value="/", method = RequestMethod.POST)
    public String save() {
    
    
        System.out.println("保存");
        return "success";
    }
}

@RestController アノテーションの説明

RESTful スタイルは、フロントエンドとバックエンドが完全に分離されているプロジェクト開発で主に使用されますが、この時点では同期リクエストは利用できず、すべてのプロセッサがデータを返す非同期リクエストになります。

この場合、すべてのハンドラー メソッドの @ResponseBody アノテーションをクラスに抽出できます。

その後、@RestController アノテーションを使用して、@Controller アノテーションと @ResponseBody アノテーションを置き換えることができます。

次のように書かれています。

//@Controller
//@ResponseBody
@RestController
@RequestMapping("/day02")
public class Day02Controller {
    
    
    ...
}

中国語の文字化けへの対処

SpringMVC が post を使用してリクエストを送信する場合、中国語パラメータの文字化けの問題が発生しますが、この場合、中国語文字化けフィルターが提供されており、これを設定するだけで済みます。

web.xmlSpringMVC 中国語文字化けフィルターの構成

	<!--在web.xml中配置过滤器,设置编码即可 CharacterEncodingFilter-->
	<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>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

おすすめ

転載: blog.csdn.net/footless_bird/article/details/127976972