SpringMVC
1. Spring MVCの概要
概要:
Spring MVC は、Spring が提供する MVC 設計パターンに基づく軽量の Web 開発フレームワークであり、本質的にはサーブレットと同等です。Spring MVC は役割分担が明確で、分業が細かく行われています。Spring MVC 自体は Spring フレームワークの一部であるため、Spring フレームワークとシームレスに統合されていると言えます。これはパフォーマンスの面で固有の利点があり、現在業界で最も主流の Web 開発フレームワークであり、最も人気のある開発スキルです。優れたフレームワークは、複雑な問題に対処する開発者の負担を軽減し、優れた内部拡張機能を備え、それをサポートする強力なユーザーグループを備えている必要があります。これはまさに Spring MVC が行ってきたことです。、
1. MVC デザインパターンの概要
MVC デザイン パターンは一般に MVC フレームワークを指し、M (モデル) はデータ モデル層を指し、V (ビュー) はビュー層を指し、C (コントローラー) はコントロール層を指します。MVCを使用する目的は、MとVの実装コードを分離し、同じプログラムでも異なる表現ができるようにすることです。その中でも、View の定義は比較的明確であり、ユーザー インターフェイスです。
例えば:
Web プロジェクトの開発では、ユーザーのリクエストにタイムリーかつ正確に対応できることが非常に重要です。ユーザーが Web ページ上の URL パスをクリックすることは、ユーザーが Web サーバーにリクエストを送信することと同じです。リクエストを取得した後、ユーザーの入力を解析し、関連する処理ロジックを実行し、最終的に正しいページにジャンプしてフィードバック結果を表示する方法は、多くの場合、制御層 (コントローラー) によって実行されます。要求プロセス中に、ユーザーの情報は、Web プロジェクトのデータ モデル レイヤー (モデル) に属する User エンティティ クラスにカプセル化されます。リクエスト表示ステージでは、リダイレクトされた結果 Web ページはビュー層 (View) に属します。
ビュー層 (View) : データの表示、ユーザー操作、データ検証、インターフェース設計、その他の機能を含む、データのフォーマットとユーザーへの表示を担当します。
制御層 (コントローラー): リクエストの処理後、リクエストの受信と転送、ビューの指定、および応答結果のクライアントへの送信を担当します。
データ モデル レイヤー (モデル) : モデル オブジェクトには最も多くの処理タスクがあり、アプリケーションの主要部分であり、データ ロジック (ビジネス ルール) の処理とデータ操作の実現 (つまり、データ モデル内のデータへのアクセス) を担当します。データベース)。
2. SpringMVCのメリットとデメリット
どのようなものにも長所と短所があります。MVC の長所と短所を見てみましょう。
アドバンテージ
1. 複数のビューがモデルを共有し、コードの再利用性が大幅に向上します
2. MVC の 3 つのモジュールは互いに独立しており、疎結合アーキテクチャです
3. コントローラーによりアプリケーションの柔軟性と構成可能性が向上します
4. ソフトウェアエンジニアリング管理に役立つ
总之,我们通过 MVC 设计模式最终可以打造出一个松耦合+高可重用性+高可适用性的完美架构。
欠点がある
1. 原理が複雑
2. システムの構造と実装の複雑さの増加
3. View のモデル データへの非効率なアクセス
MVC は小規模または中規模のプロジェクトには適していません。MVC を小規模アプリケーションに適用するのに多くの時間を費やしても、通常は無駄です。したがって、MVC デザイン パターンの使用は、特定のアプリケーション シナリオに従って決定する必要があります。
3. Spring の MVC パターンの概要
- これは、Spring が提供する MVC 設計パターンに基づく軽量の Web 開発フレームワークであり、本質的にはサーブレットと同等です。
- これは、最も明確な構造を持つ Servlet+JSP+JavaBean の実装であり、Struts などの他のフレームワークのバリアントであるか、完全に MVC システムに基づいていないのとは異なり、典型的な教科書スタイルの MVC フレームワークです。
- 役割が明確に分かれており、分業が細かく行われており、Spring フレームワークとシームレスに統合されています。Spring MVC は、最も主流の Web 開発フレームワークであり、今日の業界で最も人気のある開発スキルです。
- コントローラはサーブレットに代わって、リクエストを受信し、対応するモデルを呼び出して処理し、プロセッサが業務処理を完了した後に処理結果を返すコントローラの役割を引き受けます。Controller は対応する View を呼び出して処理結果をレンダリングし、最終的にクライアントは応答情報を取得します。
- このフレームワークは、疎結合でプラグイン可能なコンポーネント構造を採用しており、他の MVC フレームワークよりも高度に構成可能で、スケーラビリティと柔軟性が優れています。
- Spring MVC のアノテーション駆動および REST スタイルのサポートは Spring フレームワークとシームレスに統合されており、パフォーマンスに固有の利点があり、開発者にとっても他の Web フレームワークよりも開発効率が高くなります。
2. Spring MVCのビルド
1. 完全な Spring フレームワークを構築する
2. 関連する SpringMVC 依存関係を導入する
<!-- Spring-web开发和集成MVC开发的相关依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!-- spring集成junit的单元测试包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<!--日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<!--J2EE-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!--mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!-- 文件上传和下载 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
3. Spring プロジェクトの下に Web 構成ファイルを作成します
4. 構成 Tomcat を追加する
1. warexplodeパッケージがTomcatオプションに追加されていない場合は、パッケージ化を構成します
上記の手順が完了したら、Tomcat を再構成する必要があります。
5. フロントコントローラー(DispatcherServlet)の設定
Spring MVC アプリケーションを開発する場合、DispatcherServlet を web.xml にデプロイする必要がある
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 项目名称(最好可以和tomcat中配置的上下文名称一致) -->
<display-name>demoMVC</display-name>
<!-- 部署 DispatcherServlet -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 框架的前端控制器类 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 表示容器再启动时立即加载servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 处理所有URL -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
6. SpringMVC設定ファイルの作成(Springの設定項目も記述可能)
名前は springmvc-servlet.xml で、リソース ディレクトリに配置されます。
web.xmlの設定
<!-- 部署 DispatcherServlet -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 框架的前端控制器类 -->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置一个初始化参数 -->
<init-param>
<!-- 加载本地的springMVC配置文件!!!!!!!!! -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 表示容器再启动时立即加载servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
1. 簡単な試みを行い、ジャンプ ページを要求し、ジャンプ ページに応答するようにコントローラーを設定します。
コントローラクラス
package com.huawei.SpringDemo2023.classtest.controller;
//import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 模块名称:登录模块
* 模块类型:控制器(C)
* 编码人:高靖博
* 创建时间:2023/2/13
* 联系电话:18587388612
*/
public class LoginController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
System.out.println("----接收到请求");
return new ModelAndView("/WEB-INF/views/index.jsp");//将响应转发到视图
}
}
springmvc 設定ファイルの設定
<!-- name设置的是请求controller的url路径,且不要和其他的bean的name设置重复 -->
<bean name="/login" class="com.huawei.SpringDemo2023.classtest.controller.LoginController" />
3. ビューリゾルバー
ビュー・リゾルバー (ViewResolver) は Spring MVC の重要な部分であり、論理ビュー名を特定のビュー・オブジェクトに解決する役割を果たします。
1. リゾルバーの種類を表示する
1. InternalResourceViewResolver
springmvc 設定ファイルで設定します
<!-- 视图解析器 -->
<!-- 内部资源视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 视图路径前缀 -->
<property name="prefix" value="/WEB-INF/views/" />
<!-- 视图路径后缀 -->
<property name="suffix" value=".jsp" />
</bean>
今後、jstl 式が JSP ページで使用される場合、上で構成されたビュー パーサーはエラーを報告します。
解決策: jstl 関連の依存関係を直接導入する
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
4. Spring MVCの実行処理
SpringMVCの実行フローは以下の通りです。
- ユーザーはリクエスト パスをクリックして HTTP リクエスト リクエストを開始します。このリクエストは DispatcherServlet (フロント コントローラ) に送信されます。
- DispatcherServlet は 1 つ以上の HandlerMapping (プロセッサ マッパー) を要求し、実行チェーン (HandlerExecutionChain) を返します。
- DispatcherServlet は、実行チェーンによって返されたハンドラー情報を HandlerAdapter (プロセッサーアダプター) に送信します。
- HandlerAdapter は、ハンドラー情報に従って、対応するハンドラー (コントローラーと呼ばれることが多い) を見つけて実行します。
- Handler が実行されると、ModelAndView オブジェクトが HandlerAdapter (Model データ モデルと View ビュー情報を含む Spring MVC の基礎となるオブジェクト) に返されます。
- HandlerAdapter は ModelAndView オブジェクトを受信した後、それを DispatcherServlet に返します。
- DispatcherServlet が ModelAndView オブジェクトを受信すると、ViewResolver (ビュー リゾルバー) にビューを解決するよう要求します。
- ViewResolver は、View 情報に従って、対応するビュー結果を照合し、それを DispatcherServlet に返します。
- 特定の View ビューを受信した後、DispatcherServlet はビューをレンダリングし、Model 内のモデル データを View ビューのリクエスト フィールドに入力し、最終的な View (ビュー) を生成します。
- ビューは、結果をブラウザ (クライアント) に表示する役割を果たします。
5. @Controllerアノテーションと@RequestMappingアノテーション
1. @Controller アノテーション
機能: スキャンによって IOC コンテナにインスタンスを追加するコントローラー クラスを実装します。
このアノテーションを使用するには、Spring の自動パッケージ スキャンを有効にする必要があります
<!-- 自动包扫描实例注入 -->
<context:component-scan base-package="com.huawei.mvcdemo2023" />
コントローラークラスのケース
// 不需要实现Controller接口
@Controller
public class LoginController {
}
2. @RequestMapping アノテーション
@RequestMapping は、リクエストを対応するコントローラー メソッドにマッピングする役割を果たします。
アノテーションベースのコントローラークラスでは、リクエストごとに対応する処理メソッドを記述できます。
@RequestMapping アノテーションを使用して、リクエストと処理メソッドを 1 つずつ照合します。
@RequestMapping アノテーションはクラスまたはメソッドで使用できます。クラスで使用すると、リクエストに応答するクラス内のすべてのメソッドがこのアドレスを親パスとして使用することを意味します。
単純なケース:
@Controller
public class LoginController {
// 可以通过http://localhost:8080/demo/doLogin访问 且请求类型要求为GET请求
@RequestMapping(value = "/doLogin",method = RequestMethod.GET)
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
}
1. @RequestMapping アノテーションのパラメータ
1. 値パラメータ
value属性は@RequestMappingアノテーションのデフォルト属性であるため、value属性のみの場合は属性名を省略でき、他の属性がある場合はvalue属性名を記述する必要があります。
明示的な宣言:
// http://localhost:8080/demo/doLogin能访问
@RequestMapping(value = "/doLogin")
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
value 属性は暗黙的に宣言できます。
// http://localhost:8080/demo/doLogin能访问
@RequestMapping("/doLogin")
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
ワイルドカードの使用
// http://localhost:8080/demo/doLogin/aa/bb/cc 能访问
@RequestMapping(value = "/doLogin/*")
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
2. パスパラメータ
その機能は value とまったく同じですが、唯一の違いは、パスは暗黙的に宣言できず、暗黙的に宣言された値が value 属性に割り当てられることです。
// http://localhost:8080/demo/doLogin/aa/bb/cc 能访问
@RequestMapping(path = "/doLogin/*")
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
3. 名前パラメータ
Function: 要求された機能を記述します。
カンマで区切られた複数パラメータの書き込み
@RequestMapping(path = "/doLogin/*",name="测试使用")
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
4.メソッドパラメータ
機能: アクセスを許可するリクエストのタイプを指定します。それが修飾されていない場合、405 エラーがスローされます。
タイプ書き込み:
GET リクエスト: RequestMethod.GET
POST リクエスト: RequestMethod.POST
PUT リクエスト; RequestMethod.PUT
DELETE リクエスト: RequestMethod.DELETE
通常、リクエスト タイプを指定する必要があります。指定しない場合は、すべてのリクエスト タイプにアクセスできることを意味します。
// http://localhost:8080/demo/doLogin,且为GET请求能访问
@RequestMapping(value = "/doLogin",method = RequestMethod.GET)
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
5.paramsパラメータ
機能: リクエストに含める必要があるパラメータを指定し、パラメータがどのような値を保持する必要があるかを指定します。
使用法 1: 指定されたパラメータを運ばなければならないと規定されている
// http://localhost:8080/demo/doLogin?type=1,必须要有type参数,且为GET请求能访问
@RequestMapping(value = "/doLogin",params = "type",method = RequestMethod.GET)
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
使用法 2: 特定のパラメータを運ぶ必要があると規定されており、その値は何か
// http://localhost:8080/demo/doLogin?type=1,必须要有type且值为1,且为GET请求能访问
@RequestMapping(value = "/doLogin",params = "type=1",method = RequestMethod.GET)
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
6. ヘッダパラメータ
リクエストヘッダーが運ぶ必要があるパラメータと値を制御します
@RequestMapping(value = "/doLogin",headers = "Referer=http://www.xxx.com",method = RequestMethod.GET)
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
7.consumersパラメータ
リクエストの content-Type の値を制御する
// 描述请求的数据必须为json,注意是!!!请求!!!!
@RequestMapping(value = "/doLogin",consumes = "application/json",method = RequestMethod.GET)
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
3. アノテーション構成を利用して論理ビューのジャンプを実現する
コントローラー メソッドが論理ビュー名を返さない場合、URL マッピング パスは次のように論理ビュー名として解釈されます。
@RequestMapping(value = "/doLogin",method = RequestMethod.GET)
public void aa(){
System.out.println("doLogin被调用!!!!!");
}
// 则会跳转到 /WEB-INF/views/doLogin.jsp
標準的な書き方:
/**
* 返回值为String的方法,是用于跳转逻辑视图的
* @return String返回值:就是返回逻辑视图名称即可
*/
@RequestMapping(value = "/testclass/toLogin")
public String toLogin(){
System.out.println("--- 跳转到登录页面");
return "login";//返回逻辑视图名
}
汎用モジュールの親パスの記述方法
@Controller
@RequestMapping("/testclass")
public class LoginController {
/**
* 返回值为String的方法,是用于跳转逻辑视图的
* @return String返回值:就是返回逻辑视图名称即可
访问该方法:/testclass/toLogin
*/
@RequestMapping(value = "/toLogin")
public String toLogin(){
System.out.println("--- 跳转到登录页面");
return "login";//返回逻辑视图名
}
@RequestMapping(value = "/toRegister")
public String toRegister(){
System.out.println("--- 跳转到登录页面");
return "login";//返回逻辑视图名
}
}
4.コントローラメソッドパラメータ
1. メソッド内の仮パラメータは、リクエストによって渡されたパラメータを受け取るために使用されます。
/**
* 返回值为String的方法,是用于跳转逻辑视图的
* @return String返回值:就是返回逻辑视图名称即可
*/
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public String toLogin(String userName,String pwd){
System.out.println("--- 跳转到登录页面");
System.out.println("用户名:"+userName);
System.out.println("密码:"+pwd);
return "login";//返回逻辑视图名
}
テストリクエスト:
http://localhost:8080/mvc/testclass/toLogin?userName=admin&pwd=123
2. サーブレットAPIのオブジェクトをインジェクト可能
リクエスト、レスポンス、セッション
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public String toLogin(HttpSession session, HttpServletRequest request){
System.out.println("--- 跳转到登录页面");
System.out.println(session.getId());
System.out.println(request.getParameter("userName"));
return "login";//返回逻辑视图名
}
3.メソッドパラメータはModel(データモデル)です
機能: モデルとビューのデータは、レンダリングのためにビュー レイヤに返されます。
コントローラ:
// Model:相当于一个数据包
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public String toLogin(Model model){
System.out.println("--- 跳转到登录页面");
// 在jsp页面中可以使用${键的名称}取出值
model.addAttribute("name","高靖博");
return "login";//返回逻辑视图名
}
jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
登录页面
${name}
</body>
</html>
5.Controllerメソッドの戻り値
- ModelAndView (データとビューを返す)
- モデル (パラメータでモデルを定義)
- モデルのプロパティを含むマップ
- 論理ビュー名を表す文字列(ジャンプページ)
- 空所
- 他の Java タイプ
1.モデルアンドビュー
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public ModelAndView toLogin(){
System.out.println("--- 跳转到登录页面");
ModelAndView mv = new ModelAndView();
mv.setViewName("login");//设置逻辑视图名称
mv.addObject("name","高启强");//给model数据包添加数据返回到视图层渲染
return mv;
}
2.モデルはデータを返します(モデルはパラメータで定義されます)
// Model:相当于一个数据包
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public String toLogin(Model model){
System.out.println("--- 跳转到登录页面");
// 在jsp页面中可以使用${键的名称}取出值
model.addAttribute("name","高靖博");
return "login";//返回逻辑视图名
}
4. 戻り値はページジャンプを表す文字列です。
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public String toLogin(String userName,String pwd){
System.out.println("--- 跳转到登录页面");
return "login";//返回逻辑视图名
}
5.voidには戻り値がありません
リダイレクトされたビューは、URL マッピング パスと同じ名前のビューです。
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public void toLogin(String userName,String pwd){
System.out.println("--- 跳转到登录页面");
}
//跳转到 toLogin.jsp
6. Spring MVC はパラメーターを渡します (コントローラー メソッドはパラメーターを受け取ります - 関連する 5-4-1 コンテンツ)
Spring MVC コントローラーがリクエストパラメーターを受信するには多くの方法があり、get リクエストに適したもの、post リクエストに適したもの、両方に適したものもあります。主に以下の方法があります。 Entity Beanによるリクエストパラメータの受け取り 処理メソッドの仮パラメータによるリクエストパラメータの受け取り HttpServletRequest(ancestor-servlet)によるリクエストパラメータの受け取り @PathVariableによるURL内のリクエストパラメータの受け取り @RequestParamによるリクエストパラメータの受け取り@ModelAttribute を通じてリクエスト パラメータを受け取ります (習得できない可能性があります)
1. Entity Beanを利用して受信する
使用範囲: GET リクエストと POST リクエストの両方が使用可能 (PUT、DELETE)
@RequestMapping(value = "/test",method = RequestMethod.POST)
// 形参处使用自定义对象(VO对象)
public String test(UserDto user){
System.out.println("-- 测试方法");
System.out.println(user);
return "main";
}
2. 仮パラメータを列挙してリクエストパラメータを受け取る
使用範囲: GET リクエストと POST リクエストの両方が使用可能 (PUT、DELETE)
@RequestMapping(value = "/test",method = RequestMethod.POST)
// 形参处使用自定义对象(VO对象)
public String test(String name,int age){
System.out.println("-- 测试方法");
System.out.println(user);
return "main";
}
4. @PathVariable は URL 内のリクエスト パラメータを受け取ります
例: http://localhost:8080/mvc/test/admin
パス内の「admin」を切り取ってパラメータにマッピングする必要があります
長所: パラメータ名を非公開にしておく
使用範囲: GET リクエストと POST リクエストの両方が使用可能 (PUT、DELETE)
注: 仮パラメータでは、String およびその他の基本データ型とラッパー型のみを使用できます。
@RequestMapping(value = "/test/{name}/{pwd}",method = RequestMethod.POST)
public String test(@PathVariable String name,@PathVariable String pwd){
System.out.println("-- 测试方法");
System.out.println(name);
System.out.println(pwd);
return "main";
}
5. @RequestParam はリクエストパラメータを受け取ります
@RequestParam を使用します:
value 属性: 異なる名前を持つパラメーターの関連付けを実現します。
required: 必須かどうか。デフォルトは true です。これは、対応するパラメーター名がリクエストに含まれている必要があり、存在しない場合は例外がスローされることを意味します。
defaultValue: パラメータのデフォルト値
使用範囲: GET リクエストと POST リクエストの両方が使用可能 (PUT、DELETE)
注: @RequestParam パラメーターは、String およびその他の基本データ型とラッパー型のみを使用できます。
@RequestMapping(value = "/test",method = RequestMethod.POST)
public String test(@RequestParam(value = "userName",defaultValue = "妈耶!") String name, String pwd){
System.out.println("-- 测试方法");
System.out.println(name);
System.out.println(pwd);
return "main";
}
7. SpringMVC リクエストの転送とリダイレクト
1. 転送リクエスト
1. 単純なケース:
@RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(){
System.out.println("-- 测试方法");
return "forward:/testclass/test2";// forward:开头加上另一个controller方法的路径
}
2. 転送処理パラメータの受け渡し
転送プロセス中に、パラメータも一緒に渡されます。
@RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(String name){
// 假设接收name=123
System.out.println("-- 测试方法");
System.out.println(name); // 123
return "forward:/testclass/test2";
}
@RequestMapping(value = "/test2",method = RequestMethod.GET)
public String test2(String name){
System.out.println("-- 测试方法2");
System.out.println(name); //123
return "main";
}
3. 転送プロセス中に ServletAPI オブジェクトを渡します
転送プロセス中に、関連する API オブジェクトも渡されます。
注: 転送する場合、転送の送信方法と転送の受信方法、制約のリクエスト タイプが同じでなければなりません。そうでない場合は 405 が発生します。
@RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(HttpServletRequest request){
System.out.println("-- 测试方法");
request.setAttribute("name","123");
return "forward:/testclass/test2";
}
@RequestMapping(value = "/test2",method = RequestMethod.GET)
public String test2(HttpServletRequest request){
System.out.println("-- 测试方法2");
request.getAttribute("name");
return "main";
}
2. リダイレクトのリクエスト
クライアントが再要求するため、要求オブジェクトと応答オブジェクトを共有することはできません。
注: リクエストのリダイレクトは get リクエストを送信するため、post リクエストにリダイレクトすることはできません
@RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(String name){
System.out.println("-- 测试方法");
return "redirect:/testclass/test2";
}
3. 非ビューリゾルバーリソース (静的リソース) の転送またはアクセス
静的リソースのロードを構成する
xmlns:mvc="http://www.springframework.org/schema/mvc"
<!-- 静态资源目录 -->
<mvc:annotation-driven />
<mvc:resources location="/static/" mapping="/static/**" /><!-- 可以写多个 -->
静的ページへの転送をテストする
@RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(){
System.out.println("-- 测试方法");
return "forward:/static/404.html";// 转发、重定向静态资源时只能是GET请求
}
8. SpringMVC-@Serviceアノテーションと@Autowired、@Resourceアノテーション
@Service アノテーションを使用する意義は、プロジェクトの 3 層アーキテクチャ モデル: C (コントローラー コントローラー)、S (サービス ビジネス レイヤー)、D (Dao 永続レイヤー) を実現することです。
目的は、3 層デカップリングを実現し、インターフェイス指向プログラミングの手法を使用することです。
コントローラー層の場合
@Controller
@RequestMapping("/testclass")
public class LoginController {
// 推荐使用resource注解根据实现类的name注入
// 实现控制层与业务层的解耦
@Resource(name = "testClassServiceImpl")
private TestClassService testClassService;
@RequestMapping(value="/doLogin",method = RequestMethod.POST)
public String doLogin(UserDto dto,HttpSession session){
System.out.println("--- 进行登录验证");
// 控制器层直接面向接口调用即可
MyResult result = testClassService.doLogin(dto);
//忽略登录验证
session.setMaxInactiveInterval(60 * 30);
session.setAttribute("userName",dto.getUserName());
return "main";
}
}
サービスインターフェース
// 业务接口层定义业务实现的方法,建议统一返回相同结果类型,如我们课程中定义的MyResult类型
public interface TestClassService {
MyResult doLogin(UserDto dto);
}
サービスの実装
// 描述-这是一个业务实现层
// <bean id="testClassServiceImpl" class="xxxx.TestClassServiceImpl">
// service注解可添加参数(""),参数字符串描述的就是实例bean的name,提供给注入时连线使用
@Service
public class TestClassServiceImpl implements TestClassService {
public MyResult doLogin(UserDto dto) {
String sys_name = "admin";
String sys_pwd = "123456";
MyResult result = new MyResult();
if(sys_name.equals(dto.getUserName())&&sys_pwd.equals(dto.getPwd())){
result.setMsg("登录成功!");
}else{
result.setCode("9999");
result.setMsg("用户名或密码错误!");
}
return result;
}
}
9. データ型コンバータ コンバータ
機能: コントローラーメソッドがパラメーターを受け取ると、異なるタイプのデータを変換できます。
型変換は、ビューとコントローラーが相互にデータをやり取りするときに発生します。Spring MVC フレームワークは、基本型 (int、long、float、double、boolean、char など) の基本型変換をすでに実行しています。注: 組み込みの型コンバータを使用する場合、リクエスト パラメータの入力値は、受信したパラメータの型と互換性がある必要があります。そうでない場合は、400 エラーが報告されます。
SpringMVCには、Stringをintに変換するメソッドの実装など、多くのコンバータが組み込まれています。これらのコンバータは「スカラーコンバータ」と呼ばれます。
1. カスタム型コンバーター
実装プロセス:
- エンティティクラスを作成します。
- コントローラークラスを作成します。
- カスタム型コンバーター クラスを作成します。
- レジスタ型コンバータ。
- 関連するビューを作成します。
実現事例:例えば、商品情報を作成するために、ユーザーはページフォームに情報を入力する必要があります。「gaojingbo, 27, 2.3」と入力すると、プログラムで新しいユーザーが自動的に作成され、「gaojingbo」の値が name 属性に自動的に割り当てられ、「27」の値が自動的に name 属性に割り当てられることを意味します。 age 属性を指定し、自動的に「2.3」という値が割り当てられます。 height プロパティを指定します。
エンティティクラス:
@Data
public class PersonDto implements Serializable {
private String name;
private int age;
private double height;
}
コントローラーメソッド
@RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(@RequestParam("dto") PersonDto dto){
System.out.println("-- 测试方法");
System.out.println(dto);
return "main";
}
コンバータ
/**
* 模块名称:字符串转换为Person对象的类型转换器
* 模块类型:类型转换器
* 编码人:高靖博
* 创建时间:2023/2/15
* 联系电话:18587388612
*/
public class StringToPersonConverter implements Converter<String, PersonDto> {
public PersonDto convert(String source) {
//gaojingbo,18,2.8
//数据格式校验
// 1. 长度校验
String[] arr = source.split(",");
if(arr.length!=3){
System.err.println("转换的数据格式不正确,请以:名称,年龄,身高 来传递.");
}
// 2. 验证数据类型是否正确
String age = arr[1];
boolean numeric = StringUtils.isNumeric(age);
if(!numeric){
System.err.println("数据类型不正确,年龄不能是字符串文字");
}
String height = arr[2];
try{
Double dd = new Double(height);
}catch (Exception e){
System.err.println("数据类型不正确,身高不能是字符串文字");
}
PersonDto dto = new PersonDto();
dto.setName(arr[0]);
dto.setAge(Integer.valueOf(arr[1]));
dto.setHeight(Double.valueOf(arr[2]));
return dto;
}
}
springmvc設定ファイル登録コンバータ
<!-- 注册类型转换器 -->
<mvc:annotation-driven conversion-service="conversionService" />
<!-- 注册转换器工厂类 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.huawei.mvcdemo2023.testClass.converters.StringToPersonConverter" />
</list>
</property>
</bean>
テストインターフェース
http://localhost:8080/mvc/testclass/test?dto=admin,18,7.8
10. データ整形Formatter
Converter<S, T> などの Spring MVC フレームワークのフォーマッタも、あるデータ型を別のデータ型に変換できるインターフェイスです。違いは、Formatter のソース タイプは String タイプである必要があるのに対し、Converter のソース タイプは任意のデータ タイプであることができることです。Formatter は Web レイヤーに適していますが、Converter はどのレイヤーでも使用できます。したがって、フォーム内のユーザー入力を変換する必要がある場合には、コンバーターの代わりにフォーマッタを選択する必要があります。Web アプリケーションでは、HTTP で送信されたリクエストデータが String 型としてコントローラーで取得されるため、Web アプリケーションでは Converter<S, T> よりも Formatter を選択する方が合理的です。
1. 内蔵フォーマットコンバーター
- NumberFormatter: Number と String の間の解析と書式設定を実現します。
- CurrencyFormatter: 数値と文字列 (通貨記号付き) の間の解析と書式設定。
- PercentFormatter: 数値と文字列 (パーセント記号付き) の間の解析と書式設定。
- DateFormatter: 日付と文字列間の解析と書式設定を実現します。
2. 使用手順
書式設定クラスを作成し、Formatter インターフェイスを実装する
/**
* 模块名称:时间格式化工具
* 模块类型:格式化转换
* 编码人:高靖博
* 创建时间:2023/2/15
* 联系电话:18587388612
*/
public class MyDateFormatter implements Formatter<Date> {
/**
* 将String---》Date
* @param text 参数字符串
* @param locale 本机配置参数
* @return
* @throws ParseException
*/
public Date parse(String text, Locale locale){
// 时间格式化工具
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date parse = null;
try {
parse = sdf.parse(text);
} catch (ParseException e) {
System.err.println("日期格式必须为:yyyy-MM-dd");
}
return parse;
}
/**
* Date--->String
* @param object Date对象
* @param locale
* @return 日期字符串
*/
public String print(Date object, Locale locale) {
// 时间格式化工具
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String format = sdf.format(object);
return format;
}
}
レジスタフォーマッタ
<!-- 注册格式化工具 -->
<bean id="formattingConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<bean class="com.huawei.mvcdemo2023.testClass.formatters.MyDateFormatter" />
</set>
</property>
</bean>
<mvc:annotation-driven conversion-service="formattingConversionService" />
コントローラーメソッドのテスト呼び出し
@RequestMapping(value = "/test",method = RequestMethod.GET)
public String test(@RequestParam("date") Date date){
System.out.println("-- 测试方法");
System.out.println(date);
return "main";
}
11. @ModelAttribute アノテーション
パラメータの値をモデルにカプセル化し、ビュー レイヤ レンダリングの機能に戻ります。
1. @RequestMapping 以外のメソッドでアノテーションを使用し、戻り値を持たない
@ModelAttribute によって変更されたメソッドは、ターゲット コントローラー メソッドにアクセスする前に呼び出されます。
注: @ModelAttribute によって変更された複数のメソッドには、実行順序はありません。クラスは、このアノテーションによって変更された 1 つのメソッドのみを記述する必要があることが推奨されます。
@Controller
@RequestMapping("/test")
public class TestController {
// 可以拦截获取到目标请求的参数
@ModelAttribute
public void doModel(String name, Model model){
System.out.println("1. 调用doModel方法");
model.addAttribute("name",name);
}
@RequestMapping(value = "/toIndex",method= RequestMethod.GET)
public String toTest(){
System.out.println("2. toTest调用");
return "testIndex";
}
}
2. 戻り値を持つ非 @RequestMapping メソッドでアノテーションを使用する
@ModelAttribute
public String doModel2(String name, Model model){
System.out.println("1. 调用doModel2方法");
return "123";// 等同于: model.addAttribute("string","123");
}
3. @RequestMapping メソッドのパラメータでアノテーションを使用します
@ModelAttribute アノテーションのみを記述し、パラメータは記述しません
以下と同等: 1. Model オブジェクトがメソッドに挿入されます。 2. model.addAttribute メソッドが呼び出されます。
3. 添加的数据:key:被修饰参数类型的首字母小写,value:参数对象 3. 然后返回视图
@RequestMapping(value = "/toIndex",method= RequestMethod.GET)
public String toTest(@ModelAttribute UserDto dto){
// model.addAttribute("userDto",dto);
System.out.println("2. toTest调用");
System.out.println(dto);
return "testIndex";
}
@ModelAttribute アノテーションを記述してパラメータを追加する
@RequestMapping(value = "/toIndex",method= RequestMethod.GET)
public String toTest(@ModelAttribute("cxk") UserDto dto){
// model.addAttribute("cxk",dto);
System.out.println("2. toTest调用");
System.out.println(dto);
return "testIndex";
}
4. コントローラーが他のクラスから継承するメソッドを定義する
呼び出しプロセスはクラス内で ModelAttribute メソッドを定義する効果と同等ですが、コードは継承によって分離および分離されます。
ModelAttribute クラス
public class BaseController1{
@ModelAttribute
public void base1(){
System.out.println("1-1 base1");
}
}
コントローラクラス
@Controller
@RequestMapping("/test")
public class TestController extends BaseController1{
@RequestMapping(value = "/toIndex",method= RequestMethod.GET)
public String toTest(){
System.out.println("2. toTest调用");
return "testIndex";
}
}
4.ModelオブジェクトとModelAndViewオブジェクト
1. モデルオブジェクト
パケットを表します。
コントローラーメソッドのパラメーターで宣言され、使用されます。
ビュー レイヤ レンダリングにデータを追加することのみ可能
@RequestMapping(value = "/toIndex",method= RequestMethod.GET)
public String toTest(Model model){
model.addAttribute("cxk",dto);
return "testIndex";
}
2. ModelAndView オブジェクト
データ パッケージとビュー オブジェクトを表します (ビューとデータが 1 つに結合されています)
コントローラーメソッドの戻り値で使用され、手動で作成する必要があります
ビュー レイヤーのレンダリングにデータを追加し戻すだけでなく、返されたビューが誰であるかを指定することもできます。
@RequestMapping(value = "/toIndex",method= RequestMethod.GET)
public ModelAndView toTest(){
ModelAndView mv = new ModelAndView();
mv.addAttribute("cxk",dto);//添加数据
mv.setViewName("testIndex");// 指定返回的逻辑视图
}
12. SpringMVC-JSONのデータ連携
1. Jsonデータ構造
1. オブジェクトの構造
{
name:"admin",// 字符串或字符类型使用单引号或双引号描述
age:18,// 数值类型直接写数字
height:2.7,
isOk:true,
arr:[],// 描述集合使用中括号
arr2:[
18,"aaa",18.9
],
arr3:[
{
name:"张三",age:18},
{
name:"张三2",age:19}
]
}
2. 配列構造
{
11,12,13,"dasdas"
}
2. SpringMVCはJsonデータの対話型変換を実装します
ブラウザとコントローラクラス間のJSONデータ連携を実現するために、Spring MVCではデフォルトでJSON形式のリクエストレスポンスを処理するMappingJackson2HttpMessageConverter実装クラスを提供しています。この実装クラスは、Jackson オープン ソース パッケージを使用して JSON データの読み取りと書き込みを行い、Java オブジェクトを JSON オブジェクトと XML ドキュメントに変換し、JSON オブジェクトと XML ドキュメントを Java オブジェクトに変換することもできます。
アノテーションを使用して開発する場合は、@RequestBody と @ResponseBody という 2 つの重要な JSON 形式変換アノテーションが必要です。
@RequestBody : リクエスト本文のデータをメソッドの仮パラメータにバインドするために使用され、このアノテーションはメソッドの仮パラメータに適用されます。
@ResponseBody : 戻りオブジェクトを直接返すために使用され、このアノテーションはメソッドに適用されます。このアノテーションを持つメソッドは、論理ビューのジャンプ機能を実装しなくなります。
1. jsckson 依存関係をインポートする
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
インポートが成功している限り、@ResponseBody@RequestBody アノテーションは通常どおり JSON 変換および応答 JSON 関数に使用できます。
2. @RequestBody アノテーション
このアノテーションを使用してパラメータを検証する場合は、それがポストリクエストであることを必ず確認してください。
1. json オブジェクトに応答する/json リクエスト パラメーターを処理する
ログインケース:
フロントエンドコード
// 复杂json参数格式时,要使用json字符串方式提交
var param = {
userName:$("#userName").val(),
pwd:$("#pwd").val(),
arr:["张三","李四"]
};
$.ajax({
url:"<%=basePath%>/testclass/doLogin",
dataType:"json",//预计后端返回json数据
type:"POST",
async:true,
data:JSON.stringify(param),// 发送的是一个json字符串
contentType:"application/json;charset=UTF-8",// 设置请求头描述数据内容是一个json
success:function(data){
//data 后端响应的数据报文
if(data.code=="9999"){
$("#msg").html(data.msg);
}else{
$("#msg").html('');
}
},
error:function(){
alert("请求错误");
}
});
コントローラ
@RequestMapping(value="/doLogin",method = RequestMethod.POST)
@ResponseBody
// @RequestBody 保证前端发送的是json字符串才能映射,否则就会抛出415错误
public MyResult doLogin(@RequestBody UserDto dto, HttpSession session){
System.out.println("--- 进行登录验证");
MyResult result = new MyResult();
result = testClassService.doLogin(dto);
//忽略登录验证
session.setMaxInactiveInterval(60 * 30);
session.setAttribute("userName",dto.getUserName());
return result;
}
ログインを実現するための完全なケース (検証コード、ログイン検証、ログイン検証)
実装プロセス:
1. 関連クラス: 検証コード コントローラー、ログイン コントローラー、ログイン エンティティ dto、ログイン ビジネス層インターフェイス、ログイン ビジネス層実装
2. ログイン機能の処理:
1. ユーザーはフォーム (ユーザー名、パスワード、確認コード) を入力します。
2. フォームを送信し (ajax メソッドを使用してフォームを送信)、最初にフォーム検証を実行します。ユーザー名、パスワード、検証コードを入力する必要があります。また、必須フィールドが入力された後、処理のためにデータをバックエンドに送信する必要があります。保証されています
3. バックエンド検証ロジック: まず検証コードが正しいかどうかを検証し、検証コードが間違っている場合はフロントエンド エラー メッセージを返し、正しい場合はユーザー名とパスワードの検証プロセスを入力します (検証プロセスユーザー名とパスワードはビジネス実装層で完成しており、ユーザー名とパスワードは無効です。コード検証ではデータベースに接続する必要はありません)
4. 検証が終了しました。正しければホームページの JSP にジャンプします。間違っていれば、非同期で更新され、エラー メッセージが表示されます。
3. ユーザーのログインプロセスを確認します。
1. コントローラーのターゲット メソッドを呼び出す前に、ユーザーのログイン情報がセッションに保存されているかどうかを確認する必要があります。セッションが失敗した場合は、ログイン インターフェイスに戻ってエラー メッセージが表示されます。セッションが存在する場合は、プロセスを続行します。
フロントエンドJSP
ログインページ (login.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%
String basePath = request.getScheme() +"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
%>
<html>
<head>
<title>登录页面</title>
<script type="text/javascript" src="<%=basePath%>/static/lib/jquery-3.5.1.min.js" ></script>
</head>
<body>
<form>
<label>用户名</label>
<input id="userName" name="userName" placeholder="请输入用户名.." /><br/>
<label>密码</label>
<input id="pwd" name="pwd" placeholder="请输入密码.." /><br/>
<input id="reqCode" name="reqCode" placeholder="请输入验证码.." />
<img id="reqCodeImg" src="" title="点击切换验证码" style="cursor:pointer;" οnclick="getReqCode()" /><br/>
<button type="button" οnclick="doLogin()">登录</button>
<span id="msg" style="color:red;"></span>
</form>
</body>
<script>
$(function(){
//1. 请求验证码
getReqCode();
});
//进行登录
function doLogin(){
// 复杂json参数格式时,要使用json字符串方式提交
var param = {
userName:$("#userName").val(),
pwd:$("#pwd").val(),
reqCode:$("#reqCode").val()
};
//表单校验....
$.ajax({
url:"<%=basePath%>/testclass/doLogin",
dataType:"json",//预计后端返回json数据
type:"POST",
async:true,
data:JSON.stringify(param),// 发送的是一个json字符串
contentType:"application/json;charset=UTF-8",// 设置请求头描述数据内容是一个json
success:function(data){
//data 后端响应的数据报文
if(data.code=="9999"){
$("#msg").html(data.msg);
}else if(data.code=="9998"){
getReqCode();//刷新验证码
$("#msg").html('验证码过期,已刷新,请从新填写验证码');
}else{// 登录成功
$("#msg").html('');
location.href = "<%=basePath%>/testclass/toMain";
}
},
error:function(){
alert("请求错误");
}
});
}
//获取验证码
function getReqCode(){
$.ajax({
url:"<%=basePath%>/req/getCode",
dataType:"json",//预计后端返回json数据
type:"GET",
async:true,
success:function(data){
//data 后端响应的数据报文
if(data.code=="9999"){
$("#msg").html(data.msg);
}else{
$("#reqCodeImg").attr("src",data.data);
}
},
error:function(){
alert("请求错误");
}
});
}
</script>
</html>
ホームページ (main.jsp)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
主页-欢迎<%= session.getAttribute("userName")%>
// 请求其他数据的ajax
</body>
</html>
バックエンドコード
ログインコントローラ
package com.huawei.mvcdemo2023.testClass.controller;
import com.huawei.mvcdemo2023.core.dto.MyResult;
import com.huawei.mvcdemo2023.testClass.dto.UserDto;
import com.huawei.mvcdemo2023.testClass.service.TestClassService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
/**
* 模块名称:登录模块
* 模块类型:控制器(C)
* 编码人:高靖博
* 创建时间:2023/2/14
* 联系电话:18587388612
*/
// 不需要实现Controller接口
@Controller
@RequestMapping("/testclass")
public class LoginController {
@Resource(name = "testClassServiceImpl")
private TestClassService testClassService;
/**
* 跳转到登录页面
* @return
*/
@RequestMapping(value = "/toLogin",method = RequestMethod.GET)
public String toLogin(){
System.out.println("-- 跳转到登录页面");
return "login";
}
/**
* 跳转到主页页面
* @return
*/
@RequestMapping(value = "/toMain",method = RequestMethod.GET)
public String toMain(){
System.out.println("-- 跳转到主页页面");
return "main";
}
@RequestMapping(value="/doLogin",method = RequestMethod.POST)
@ResponseBody
public MyResult doLogin(@RequestBody UserDto dto, HttpSession session){
System.out.println("--- 进行登录验证");
MyResult result = new MyResult();
Object reqCode = session.getAttribute("reqCode");
if(reqCode==null){
result.setMsg("验证码过期请刷新!");
result.setCode("9998");
return result;
}else{
String reqCodeStr = (String) reqCode;
if(!reqCodeStr.equalsIgnoreCase(dto.getReqCode())){
result.setMsg("验证码错误!");
result.setCode("9999");
return result;
}
}
result = testClassService.doLogin(dto);
if(result.getCode().equals("0000")){
//登录成功时再设置session
session.setMaxInactiveInterval(60 * 30);
session.setAttribute("userName",dto.getUserName());
}
return result;
}
/**
* 跳转到注册页面
* @return
*/
@RequestMapping(value = "/toRegister",method = RequestMethod.GET)
public String toRegister(){
System.out.println("-- 跳转到注册页面");
return "register";
}
}
13. SpringMVC-Restful の統合
springmvc 5.2.3 バージョンは RESTful 仕様を実装しました
put または delete リクエストが対応するメソッドに入らない場合
フィルターは web.xml ファイルで構成する必要があります
14. SpringMVCフィルター
フィルターとは何ですか?
サーブレットコンテナに依存します。実装に関しては、関数コールバックに基づいて、ほとんどすべてのリクエストをフィルタリングできますが、欠点は、コンテナの初期化時にフィルタ インスタンスを1 回しか呼び出せないことです。
フィルターを使用する目的は、フィルター内の文字エンコーディングを変更する、フィルター内の HttpServletRequest の一部のパラメーターを変更するなど、取得したいデータを取得するためにいくつかのフィルター操作を実行することです: 卑劣なテキスト、危険な文字などをフィルターする。
つまり、フィルタは実際にはすべてのリクエストをフィルタリングし、リクエストによって伝送されるデータを取得するか、リクエストの一部のパラメータを変更します。
1. 組み込みフィルター - 文字セットフィルター
web.xmlでの設定
<!-- springMVC自带过滤器- 实现参数、响应编解码一致的过滤器 -->
<filter>
<description>字符集过滤器</description>
<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>
<!-- forceEncoding:true
请求、响应都会进行字符编码集的转换
request.setCharacterEncoding(“”);
response.setCharacterEncoding(“”);
forceEncoding:false (默认)
只在请求时转换字符编码集
request.setCharacterEncoding(“”);
-->
<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>
2. カスタムフィルター
- Filter インターフェースを実装するクラスを定義する
- フィルター インターフェイスを実装する 3 つのメソッド: 初期化メソッド、dofilter メソッド、および破棄メソッド
- web.xml でフィルターを構成する
chain.doFilter(request, response); このメソッドの呼び出しは分水界として機能します。実際、サーブレットの doService() メソッドの呼び出しはこのメソッド内で実行されます。
フィルターケース
public class MyTestFilter implements Filter {
//初始化方法
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("--- MyTestFilter初始化");
String what = filterConfig.getInitParameter("what");//可以获取web.xml 中filter标签里配置的初始化参数
System.out.println(what);
}
//执行拦截方法
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("--- 进入过滤器:MyTestFilter");
//胡作非为(请求添加参数、改变contentType、改变head)
servletRequest.setAttribute("name","cxk");
//控制请求是否放行
filterChain.doFilter(servletRequest,servletResponse);//放行
}
//销毁方法
public void destroy() {
System.out.println("--- MyTestFilter被销毁");
}
}
フィルタを設定する
<!-- 自定义过滤器 -->
<filter>
<description>自定义过滤器</description>
<filter-name>myFilter1</filter-name>
<filter-class>com.huawei.mvcdemo2023.testClass.filters.MyTestFilter</filter-class>
<init-param>
<param-name>what</param-name>
<param-value>123456</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myFilter1</filter-name>
<url-pattern>/test/*</url-pattern>
</filter-mapping>
15. SpringMVC-インターセプター
インターセプターとは何ですか?
これは Java の jdk 動的生成に基づいて実装され、HandlerInterceptorインターフェイスを実装します。サーブレットコンテナに依存せず、インターセプタはコントローラメソッドを対象としており、すべてのクラスを取得でき、クラス内のすべてのメソッドにインターセプトを実装でき、粒度が小さく、インターセプタはサービスを注入でき、ビジネスロジックを呼び出すこともできます。
インターセプターの実装
• HandlerInterceptorインターフェイス、またはHandlerInterceptor インターフェイスを継承する実装クラス (HandlerInterceptorAdapter など) を実装することによって定義されます。
• WebRequestInterceptor インタフェース、またはWebRequestInterceptor インタフェースを継承した実装クラスを実装して定義します。
メソッドの説明
HandlerInterceptor インターフェイスを作成し、次のようにインターフェイスに3 つのメソッドを実装します。
preHandle() :コントローラの処理要求メソッドより前に実行されるメソッドで、戻り値は後続の動作を中断するかどうかを示します。trueが下方向に実行を継続することを示し、false が後続の動作を中断することを示します。
postHandle( ) : このメソッドは、コントローラーの処理リクエスト メソッドが呼び出された後ビューが解析される前に実行されます。このメソッドは、リクエスト ドメイン内のモデルとビューをさらに変更するために使用できます。
afterCompletion() : このメソッドは、コントローラの処理要求メソッドが実行された後、つまりビューのレンダリングが完了した後に実行され、リソースのクリーニングやログ情報の記録などのいくつかのタスクを実現できます。
インターセプターコード:
public class MyTestInterceptor implements HandlerInterceptor {
// 在调用目标controller方法“前”会被调用
// 返回值:true代表放行,false代表拦截住不继续往下执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器:preHandle");
return true;
}
// 在调用目标controller方法“后”,解析视图之"前"
// 可以让编程者,控制最终视图的走向、以及视图中携带的数据内容是否发生更改
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("拦截器:postHandle");
}
// 在调用目标controller方法“后”,以及视图渲染完成,数据返回成功才执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("拦截器:afterCompletion");
}
}
springmvc 設定ファイル内
mvc:interceptors : この要素は、インターセプターのセットを構成するために使用されます。
: この要素は mvc:interceptors の子要素であり、すべてのリクエストをインターセプトするグローバル インターセプターを定義するために使用されます。
mvc:interceptor : この要素は、指定されたパスのインターセプターを定義するために使用されます。
mvc:mapping : この要素は mvc:interceptor の子要素であり、その属性パスで定義されるインターセプターのパスを構成するために使用されます。path の属性値が /** の場合はすべてのパスをインターセプトすることを意味し、値が /gotoTest の場合は /gotoTest で終わるすべてのパスをインターセプトすることを意味します。リクエスト パスにインターセプトする必要のないコンテンツが含まれている場合は、 < mvc :exclude-mapping> サブ要素を通じて構成できます。
<!-- 拦截器的配置 -->
<mvc:interceptors>
<!-- 定义一个拦截器 -->
<mvc:interceptor>
<!-- 哪些路径进入拦截器 -->
<mvc:mapping path="/**"></mvc:mapping>
<!-- 描述自定义拦截器实例 -->
<bean class="com.huawei.mvcdemo2023.testClass.interceptors.MyTestInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
フィルターとインターセプターの実行プロセス
最初にフィルター、次にブロッカー。
preHandler はハンドラー マッパー コールバック、postHandler は handlerApter コールバックです。
16. SpringMVC ファイルのアップロード
2. 2つの実装モード
1. CommonsMultipartResolver に基づく
1. 依存関係をインポートする
<!-- 文件上传和下载 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
2. springmvc 構成ファイルでファイルアップロードパーサーを構成します
<!-- 文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 单个请求文件上传最大值 -->
<property name="maxUploadSize" value="50000000000" />
<!-- 文件上传字符编码集 -->
<property name="defaultEncoding" value="UTF-8" />
</bean>
1. フォームの送信とファイルのアップロード
フロントエンドコード
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%
String basePath = request.getScheme() +"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
%>
<html>
<head>
<title>测试</title>
<script type="text/javascript" src="<%=basePath%>/static/lib/jquery-3.5.1.min.js" ></script>
</head>
<body>
<form action="<%=basePath%>/test/fileUpload" method="POST" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="确定上传" />
</form>
</body>
</html>
2. Ajax 提出ファイルのアップロード
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%
String basePath = request.getScheme() +"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
%>
<html>
<head>
<title>测试</title>
<script type="text/javascript" src="<%=basePath%>/static/lib/jquery-3.5.1.min.js" ></script>
</head>
<body>
<form id="fileForm">
<input type="file" name="file" />
<input type="button" οnclick="doFileUpload()" value="确定上传" />
</form>
</body>
<script>
function doFileUpload(){
// ajax 模拟表单提交
var formData = new FormData($("#fileForm")[0]);
$.ajax({
url:"<%=basePath%>/test/fileUpload",
dataType:"json",
type:"POST",
async:true,
cache:false,// 去除缓存影响
processData: false, // 规定通过请求发送的数据是否转换为查询字符串,设置为否
contentType:false,// 不设置任何的mime类型以二进制方式发送
data:formData,
success:function(data){
console.dir(data);
},
error:function(){
alert("请求错误");
}
});
}
</script>
</html>
3. バックエンドはファイルを解析し、ディスクに書き込み、アップロードを完了します。
ディスクに書き込むパスは設定ファイルに書き込むことができます
web.xml 配置文件中配置:
<context-param>
<param-name>uploadPath</param-name>
<param-value>F:\\sysFile</param-value>
</context-param>
コントローラーメソッド
@RequestMapping(value = "/fileUpload",method = RequestMethod.POST)
@ResponseBody
public MyResult fileUpload(MultipartFile file, HttpServletRequest request){
MyResult res = new MyResult();
System.out.println("--- 文件上传!");
//文件要上传的位置(通过配置文件加载)
ServletContext servletContext = request.getServletContext();
String uploadPath = servletContext.getInitParameter("uploadPath");
//上传文件
try {
byte[] fileBytes = file.getBytes();
//文件名称
String originalFilename = file.getOriginalFilename();
//文件后缀
String fileSub = originalFilename.substring(originalFilename.lastIndexOf("."));
//加密的文件名称
String fileID = UUID.randomUUID().toString().replaceAll("-", "");
//要创建的文件路径
String newFile = uploadPath + "\\" + fileID + fileSub;
//写出
file.transferTo(new File(newFile));
} catch (IOException e) {
e.printStackTrace();
res.setMsg("文件上传出错!");
res.setCode("9999");
return res;
}
res.setMsg("文件上传成功!");
return res;
}
17. SpringMVCファイルのダウンロード
1. サーブレットメソッドを使用してファイルをダウンロードする
@RequestMapping(value = "/filedownload",method = RequestMethod.GET)
@ResponseBody
public void filedownload(HttpServletRequest request, HttpServletResponse response){
System.out.println("--- 文件下载");
//要下载的文件。带后缀(固定下载这个文件)
String needDownLoad = "d10fb3edd4cc43b7be5da10aef985fcc.png";
//设置响应头
response.setHeader("Content-Type", "application/x-msdownload");//描述是文件下载
try {
response.setHeader("Content-Disposition", "attachment;filename="+this.toUTF8(needDownLoad));//下载文件的名称
} catch (UnsupportedEncodingException e) {
System.err.println("文件下载错误:文件名称编码错误!");
e.printStackTrace();
}
//获取文件保存的文件夹
ServletContext servletContext = request.getServletContext();
String uploadPath = servletContext.getInitParameter("uploadPath");
try {
//读出来
FileInputStream fileInputStream = new FileInputStream(uploadPath + "\\" + needDownLoad);
byte [] fileByte = new byte[fileInputStream.available()];
fileInputStream.read(fileByte);
fileInputStream.close();
//写出去(使用响应对象写出)
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(fileByte);
outputStream.flush();
outputStream.close();
} catch (IOException e) {
System.err.println("文件下载错误!");
e.printStackTrace();
}
}
// 将字符串进行utf-8编解码
private String toUTF8(String tarStr) throws UnsupportedEncodingException {
byte[] bytes = tarStr.getBytes("UTF-8");
String s = new String(bytes, "UTF-8");
return s;
}
2. Mvc+commonse-ioファイルのダウンロード方法
@RequestMapping(value = "/mvcDownload",method=RequestMethod.GET)
public ResponseEntity<byte[]> mvcDownload(HttpServletRequest request){
System.out.println("-- mvc文件下载");
//要下载的文件。带后缀(固定下载这个文件)
String needDownLoad = "d10fb3edd4cc43b7be5da10aef985fcc.png";
//获取文件保存的文件夹
ServletContext servletContext = request.getServletContext();
String uploadPath = servletContext.getInitParameter("uploadPath");
//设置响应头
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);//描述是文件下载
httpHeaders.setContentDispositionFormData("attachment", needDownLoad);// 描述下载文件的名称
ResponseEntity<byte[]> responseEntity = null;
try {
responseEntity = new ResponseEntity<byte[]>(
FileUtils.readFileToByteArray(new File(uploadPath + "\\" + needDownLoad)),// 将文件读取成byte数组
httpHeaders,//设置响应头
HttpStatus.CREATED // 设置Http响应的初始状态
);
} catch (IOException e) {
System.err.println("mvc文件下载错误!");
e.printStackTrace();
}
return responseEntity;
}