国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

ホームページ Java &#&チュートリアル Spring Security と OAuth について

Spring Security と OAuth について

Jan 14, 2025 pm 04:05 PM

この記事では、Spring セキュリティについて調(diào)査し、OAuth 2.0 を使用した認(rèn)証システムを構(gòu)築します。

Spring Security は、Java ベースのアプリケーションに堅(jiān)牢な認(rèn)証およびアクセス制御メカニズムを?qū)g裝するための、強(qiáng)力で高度にカスタマイズ可能なフレームワークです。これは Spring エコシステムの中核コンポーネントであり、Web アプリケーション、REST API、およびその他のバックエンド サービスを保護(hù)するために広く使用されています。 Spring Security を使用すると、アプリケーションで安全なプラクティスを構(gòu)築および適用するための強(qiáng)固な基盤が得られます。


Spring Security の仕組み

Spring Security の動(dòng)作方法について詳しく説明する前に、Java ベースの Web サーバーの リクエスト処理ライフサイクル を理解することが重要です。 Spring Security はこのライフサイクルにシームレスに統(tǒng)合され、受信リクエストを保護(hù)します。


Spring Security によるリクエスト処理ライフサイクル

Spring Security を使用して Spring ベースのアプリケーションで HTTP リクエストを処理するライフサイクルには、いくつかの段階が含まれており、それぞれがリクエストの処理、検証、セキュリティ保護(hù)において重要な役割を果たします。


1. クライアントリクエスト

クライアント (ブラウザ、モバイル アプリ、Postman などの API ツールなど) が HTTP リクエストをサーバーに送信すると、ライフサイクルが始まります。

例:

GET /api/admin/dashboard HTTP/1.1


2. サーブレットコンテナ

サーブレット コンテナ (例: Tomcat) はリクエストを受信し、それを Spring アプリケーションのフロント コントローラーである DispatcherServlet に委任します。ここからアプリケーションの処理パイプラインが開(kāi)始されます。


3. Spring セキュリティ フィルター チェーン

DispatcherServlet がリクエストを処理する前に、Spring Security のフィルター チェーン がリクエストをインターセプトします。フィルター チェーンは一連のフィルターであり、それぞれが特定のセキュリティ タスクの処理を擔(dān)當(dāng)します。これらのフィルターは、リクエストがアプリケーション ロジックに到達(dá)する前に認(rèn)証および認(rèn)可の要件を満たしていることを確認(rèn)します。

チェーン內(nèi)のキーフィルター:

  1. 認(rèn)証フィルター:

    これらのフィルターは、ユーザー名/パスワード、JWT、セッション Cookie などの有効な認(rèn)証情報(bào)がリクエストに含まれているかどうかを検証します。

  2. 認(rèn)可フィルター:

    認(rèn)証後、これらのフィルターは、認(rèn)証されたユーザーが、要求されたリソースにアクセスするために必要なロールまたは権限を持っていることを確認(rèn)します。

  3. その他のフィルター:

* **CsrfFilter**: Validates CSRF tokens to prevent Cross-Site Request Forgery attacks.

* **CorsFilter**: Manages Cross-Origin Resource Sharing (CORS) rules for secure API access from different domains.

* **ExceptionTranslationFilter**: Handles security-related exceptions (e.g., invalid credentials) and sends appropriate responses to the client.

4. セキュリティコンテキスト

認(rèn)証が成功すると、Spring Security は Authentication オブジェクトを作成し、それを SecurityContext に保存します。このオブジェクトはスレッドローカル ストレージに保存されることが多く、リクエストのライフサイクル全體を通じてアクセスできます。

認(rèn)証オブジェクト:

  • プリンシパル: 認(rèn)証されたユーザー (ユーザー名など) を表します。

  • 資格情報(bào): JWT トークンやパスワードなどの認(rèn)証の詳細(xì)が含まれます。

  • 権限: ユーザーに割り當(dāng)てられたロールと権限が含まれます。

フィルター チェーン內(nèi)のフローの例:

  • リクエストは認(rèn)証フィルターを通過(guò)します。

  • 資格情報(bào)が有効な場(chǎng)合、Authentication オブジェクトが作成され、SecurityContext に追加されます。

  • 認(rèn)証情報(bào)が無(wú)効な場(chǎng)合、ExceptionTranslationFilter はクライアントに 401 Unauthorized 応答を送信します。


5. DispatcherServlet

リクエストが Spring Security フィルター チェーンを正常に通過(guò)すると、DispatcherServlet が引き継ぎます。

  1. ハンドラーマッピング:

    URL と HTTP メソッドに基づいて、受信リクエストを適切なコントローラー メソッドにマッピングします。

  2. コントローラー呼び出し:

    マップされたコントローラーはリクエストを処理し、適切なレスポンスを返します。多くの場(chǎng)合、サービスやリポジトリなどの他の Spring コンポーネントの助けを借ります。

Spring Security がライフサイクルにどのように適合するか

Spring Security はフィルターを通じてこのライフサイクルに統(tǒng)合され、初期段階でリクエストをインターセプトします。リクエストがアプリケーション ロジックに到達(dá)するまでに、リクエストはすでに認(rèn)証および許可されており、正當(dāng)なトラフィックのみがコア アプリケーションによって処理されることが保証されます。


Spring Security の設(shè)計(jì)では、認(rèn)証、認(rèn)可、その他のセキュリティ対策が宣言的に処理されることを保証し、開(kāi)発者が必要に応じて動(dòng)作をカスタマイズまたは拡張できる柔軟性を提供します。これは、ベスト プラクティスを強(qiáng)制するだけでなく、最新のアプリケーションにおける複雑なセキュリティ要件の実裝を簡(jiǎn)素化します。

Understanding Spring Security and OAuth

Spring Security コンポーネント: フィルター チェーンを超えて

Spring Security の フィルター チェーン について説明しました。次に、認(rèn)証と認(rèn)可のプロセスで重要な役割を果たす他の重要なコンポーネントについて詳しく説明します。

認(rèn)証マネージャー

AuthenticationManager は、ユーザーの資格情報(bào)を検証し、それらが有効かどうかを判斷するために使用される?yún)g一のメソッド、authenticate(Authentication 認(rèn)証) を定義するインターフェースです。 AuthenticationManager は、複數(shù)のプロバイダを登録できるコーディネーターと考えることができ、リクエストの種類に基づいて、認(rèn)証リクエストを正しいプロバイダに配信します。

認(rèn)証プロバイダー

AuthenticationProvider は、資格情報(bào)に基づいてユーザーを認(rèn)証するためのコントラクトを定義するインターフェイスです。これは、ユーザー名/パスワード、OAuth、LDAP などの特定の認(rèn)証メカニズムを表します。複數(shù)の AuthenticationProvider 実裝を共存させることができるため、アプリケーションはさまざまな認(rèn)証戦略をサポートできます。

コアコンセプト:

  1. 認(rèn)証オブジェクト:

    AuthenticationProvider は、ユーザーの資格情報(bào) (ユーザー名やパスワードなど) をカプセル化する Authentication オブジェクトを処理します。

  2. 認(rèn)証メソッド:

    各 AuthenticationProvider は、実際の認(rèn)証ロジックが存在する、authenticate(Authentication 認(rèn)証) メソッドを?qū)g裝します。このメソッド:

* **CsrfFilter**: Validates CSRF tokens to prevent Cross-Site Request Forgery attacks.

* **CorsFilter**: Manages Cross-Origin Resource Sharing (CORS) rules for secure API access from different domains.

* **ExceptionTranslationFilter**: Handles security-related exceptions (e.g., invalid credentials) and sends appropriate responses to the client.
  1. メソッドをサポートします: support(Class>authentication) メソッドは、AuthenticationProvider が指定されたタイプの認(rèn)証を処理できるかどうかを示します。これにより、Spring Security は特定の認(rèn)証リクエストを処理するための正しいプロバイダーを決定できるようになります。

:

  • データベースを利用した AuthenticationProvider がユーザー名とパスワードを検証します。

  • OAuth ベースの AuthenticationProvider は、外部 ID プロバイダーによって発行されたトークンを検証します。

ユーザー詳細(xì)サービス

UserDetailsS??ervice は、Spring ドキュメントでユーザー固有のデータをロードするコア インターフェイスとして説明されています。これには、パラメーターとしてユーザー名を受け取り、 ==User== アイデンティティ オブジェクトを返す単一のメソッド loadUserByUsername が含まれています。基本的には、loadUserByUsername メソッドをオーバーライドする UserDetailsS??ervice のクラスを作成して実裝します。

* Validates the user’s credentials.

* Returns an authenticated `Authentication` object upon success.

* Throws an `AuthenticationException` if authentication fails.

これら 3 つがどのように連攜するかというと、AuthenticationManager は AuthenticationProvider に、指定された Provider の種類に従って認(rèn)証を?qū)g行するよう依頼し、UserDetailsS??ervice 実裝は AuthenticationProvider が userdetails を証明するのを支援します。

設(shè)定などに進(jìn)む前に、JWT ベースの認(rèn)証のための Spring Security の簡(jiǎn)潔なフローを次に示します。

1. ユーザーリクエスト

  • ユーザーは、認(rèn)証情報(bào) (ユーザー名とパスワード) または JWT トークン (ヘッダー內(nèi)) を使用して認(rèn)証されたエンドポイントにリクエストを送信し、リクエストは認(rèn)証フィルターに渡されます

  • AuthenticationFilter (例: UsernamePasswordAuthenticationFilter):

    • 送信された資格情報(bào) (通常はユーザー名とパスワードの形式) に基づいてユーザー認(rèn)証を処理します。ここで UsernamePasswordAuthenticationFilter が活躍します。
    • リクエストをリッスンし、ユーザー名とパスワードを抽出して、AuthenticationManager に渡します。
    • しかし、ユーザー名とパスワードは渡しません。トークンだけを渡します。そのため、この AuthenticationFilter の前に、ユーザーが認(rèn)証されており、ユーザー名とパスワードをチェックする必要がないことを認(rèn)証プロセスに伝えるフィルターが必要です。これは、JWTFilter
    • を作成することで行われます。

2.JWTフィルター

このカスタム フィルターは OncePerRequestFilter を拡張し、 UsernamePasswordAuthenticationFilter の前に配置され、リクエストからトークンを抽出して検証します。

トークンが有効な場(chǎng)合、UsernamePasswordAuthenticationToken を作成し、そのトークンをセキュリティ コンテキストに設(shè)定します。これにより、リクエストが認(rèn)証されたことを Spring セキュリティに伝え、このリクエストが UsernamePasswordAuthenticationFilter に渡されると、UsernamePasswordAuthenticationToken を持っているためそのまま渡されます

* **CsrfFilter**: Validates CSRF tokens to prevent Cross-Site Request Forgery attacks.

* **CorsFilter**: Manages Cross-Origin Resource Sharing (CORS) rules for secure API access from different domains.

* **ExceptionTranslationFilter**: Handles security-related exceptions (e.g., invalid credentials) and sends appropriate responses to the client.

UserDetails クラスを使用してユーザー名とパスワードを認(rèn)証した後、トークンの代わりにユーザー名とパスワードを渡した場(chǎng)合、この UsernamePasswordAuthenticationToken は AuthenticationManager と AuthenticationProvider を使用して生成されます。

3. 認(rèn)証マネージャー

  • AuthenticationManager: これは認(rèn)証リクエストを受け取り、それを設(shè)定した適切な AuthenticationProvider に委任します。
* Validates the user’s credentials.

* Returns an authenticated `Authentication` object upon success.

* Throws an `AuthenticationException` if authentication fails.

4.認(rèn)証プロバイダ

  • UserDetailsS??ervice: AuthenticationProvider は UserDetailsS??ervice を使用して、ユーザー名に基づいてユーザーの詳細(xì)を読み込みます。そして、これを UserDetailsS??ervice

  • の実裝で提供します。
  • 資格情報(bào)の検証: 提供されたパスワードとユーザーの詳細(xì)に保存されているパスワードを比較します (通常は PasswordEncoder を使用します)。

package com.oauth.backend.services;

import com.oauth.backend.entities.User;
import com.oauth.backend.repositories.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;


@Component
public class CustomUserDetailsService implements UserDetailsService {
    private final UserRepository userRepository;

    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = userRepository.findByUsername(username);
        if(user==null){
            throw new UsernameNotFoundException(username);
        }
        return new UserDetailsImpl(user);
    }
    public UserDetails loadUserByEmail(String email) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(email);
        if(user==null){
            throw new UsernameNotFoundException(email);
        }
        return new UserDetailsImpl(user);
    }
}

Spring セキュリティが何をすべきかを認(rèn)識(shí)できるように、これらすべてのさまざまなフィルターと Bean を構(gòu)成する必要があるため、すべての構(gòu)成を指定する構(gòu)成クラスを作成します。

@Component
public class JWTFilter extends OncePerRequestFilter {

    private final JWTService jwtService;
    private final UserDetailsService userDetailsService;
    public JWTFilter(JWTService jwtService,UserDetailsService userDetailsService) {
        this.jwtService = jwtService;
        this.userDetailsService = userDetailsService;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        final String authHeader = request.getHeader("Authorization");

        if(authHeader == null || !authHeader.startsWith("Bearer")) {
            filterChain.doFilter(request,response);
            return;
        }

        final String jwt = authHeader.substring(7);
        final String userName = jwtService.extractUserName(jwt);

        Authentication authentication
                = SecurityContextHolder.getContext().getAuthentication();

        if(userName !=null  && authentication == null) {
            //Authenticate
            UserDetails userDetails
                    = userDetailsService.loadUserByUsername(userName);

            if(jwtService.isTokenValid(jwt,userDetails)) {
                UsernamePasswordAuthenticationToken authenticationToken
                        = new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );

                SecurityContextHolder.getContext()
                        .setAuthentication(authenticationToken);
            }
        }

        filterChain.doFilter(request,response);
    }



}

これまで Spring Security を使用して認(rèn)証を理解し、構(gòu)成してきました。ここからはテストしてみます。

AuthController (ログインと登録を処理します) と ProductController (ダミーの保護(hù)されたコントローラー) の 2 つのコントローラーを備えたシンプルなアプリを作成します

* **CsrfFilter**: Validates CSRF tokens to prevent Cross-Site Request Forgery attacks.

* **CorsFilter**: Manages Cross-Origin Resource Sharing (CORS) rules for secure API access from different domains.

* **ExceptionTranslationFilter**: Handles security-related exceptions (e.g., invalid credentials) and sends appropriate responses to the client.
* Validates the user’s credentials.

* Returns an authenticated `Authentication` object upon success.

* Throws an `AuthenticationException` if authentication fails.
package com.oauth.backend.services;

import com.oauth.backend.entities.User;
import com.oauth.backend.repositories.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;


@Component
public class CustomUserDetailsService implements UserDetailsService {
    private final UserRepository userRepository;

    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        User user = userRepository.findByUsername(username);
        if(user==null){
            throw new UsernameNotFoundException(username);
        }
        return new UserDetailsImpl(user);
    }
    public UserDetails loadUserByEmail(String email) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(email);
        if(user==null){
            throw new UsernameNotFoundException(email);
        }
        return new UserDetailsImpl(user);
    }
}
@Component
public class JWTFilter extends OncePerRequestFilter {

    private final JWTService jwtService;
    private final UserDetailsService userDetailsService;
    public JWTFilter(JWTService jwtService,UserDetailsService userDetailsService) {
        this.jwtService = jwtService;
        this.userDetailsService = userDetailsService;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        final String authHeader = request.getHeader("Authorization");

        if(authHeader == null || !authHeader.startsWith("Bearer")) {
            filterChain.doFilter(request,response);
            return;
        }

        final String jwt = authHeader.substring(7);
        final String userName = jwtService.extractUserName(jwt);

        Authentication authentication
                = SecurityContextHolder.getContext().getAuthentication();

        if(userName !=null  && authentication == null) {
            //Authenticate
            UserDetails userDetails
                    = userDetailsService.loadUserByUsername(userName);

            if(jwtService.isTokenValid(jwt,userDetails)) {
                UsernamePasswordAuthenticationToken authenticationToken
                        = new UsernamePasswordAuthenticationToken(
                        userDetails,
                        null,
                        userDetails.getAuthorities()
                );

                SecurityContextHolder.getContext()
                        .setAuthentication(authenticationToken);
            }
        }

        filterChain.doFilter(request,response);
    }



}
@Bean  
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception{  
return config.getAuthenticationManager();  
}
@Bean  
public AuthenticationProvider authenticationProvider(){  
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();  
authenticationProvider.setUserDetailsService(userDetailsServiceImpl);  
authenticationProvider.setPasswordEncoder(passwordEncoder);  
return authenticationProvider;  
}

これまで、登録、ログイン、検証を?qū)g裝してきましたが、Login With Google/Github 機(jī)能も追加したい場(chǎng)合は、OAuth2.0 を使用して実行できます

OAuth 2.0

OAuth 2.0 は、ユーザーが他のプラットフォーム (Google Drive や Github など) に保存されているリソースへのアクセスをサードパーティのアプリケーションに、それらのプラットフォームの資格情報(bào)を共有せずに許可できるようにする認(rèn)証用に作成されたプロトコルです。

主に、「Google でログイン」、「github でログイン」などのソーシャル ログインを有効にするために使用されます。

Google、Facebook、Github などのプラットフォームは、このソーシャル サインインまたはアクセスの承認(rèn)のために OAuth 2.0 プロトコルを?qū)g裝する承認(rèn)サーバーを提供します。

OAuth 2.0 の主要な概念

  • リソース所有者

  • クライアント

  • 認(rèn)可サーバー

  • リソースサーバー

  • アクセストークン

  • スコープ

  • 助成金

次に、各コンセプトを 1 つずつ見(jiàn)ていきます

リソース所有者

リソース所有者は、サードパーティ アプリケーション (あなたのアプリケーション) を承認(rèn)したいユーザーです。

クライアント

これは、リソース サーバーからデータまたはリソースにアクセスしようとしている (サードパーティの) アプリケーションです。

リソースサーバー

これはユーザーのデータが保存されるサーバーであり、サードパーティのアプリケーションによってアクセスされます。

認(rèn)可サーバー

リソース所有者を認(rèn)証し、クライアント (Google アカウントなど) にアクセス トークンを発行するサーバー。

アクセストークン

認(rèn)可サーバーによってクライアントに発行される資格情報(bào)。これにより、クライアントはユーザーに代わってリソース サーバーにアクセスできるようになります。通常、有効期間は短く、すぐに期限切れになるため、ユーザーが再度認(rèn)証する必要がないように、このアクセス トークンを更新するためのリフレッシュ トークンも提供されます。

スコープ

ユーザーによって付與される特定の権限。クライアントがユーザーのデータに対してできることとできないことを定義します。たとえば、承認(rèn)の場(chǎng)合は、プロフィール、名前などのユーザー情報(bào)のみが必要ですが、ファイルアクセスの場(chǎng)合は別のスコープが必要です。

助成金

クライアント アプリケーションが認(rèn)可サーバーからアクセス トークンを取得できる方法を指します。許可は、クライアント アプリケーションがリソース所有者の保護(hù)されたデータへのアクセスを許可されるプロセスと條件を定義します。

クライアント シークレットやその他の認(rèn)証情報(bào)をブラウザに公開(kāi)する必要がないため、安全です

OAuth 2.0 によって提供される、主に使用される 2 つの許可タイプがあります

  1. 認(rèn)可コードグラント

    これは最も使用されているタイプの許可/メソッドであり、最も安全であり、サーバー側(cè)アプリケーション用です

    この例では、クライアントからバックエンドに認(rèn)可コードが與えられ、バックエンドはクライアントにアクセス トークンを與えます。

    プロセス:

    1. クライアントはユーザーを認(rèn)可サーバーにリダイレクトします。
    2. ユーザーはログインして同意します。
    3. 認(rèn)可サーバーは認(rèn)可コードを発行します。
    4. クライアントは、バックエンドと認(rèn)証コードを交換してアクセス トークンを取得します。
  2. 暗黙的な許可

    シングルページ アプリ (SPA) またはバックエンドのないアプリケーションによって使用されます。この場(chǎng)合、アクセス トークンはブラウザ自體で直接生成され、発行されます。

    プロセス:

    1. クライアントはユーザーを認(rèn)可サーバーにリダイレクトします。
    2. ユーザーはログインして同意します。
    3. 認(rèn)可サーバーはアクセストークンを直接発行します。

完全に理解するために両方を個(gè)別に実裝しますが、最初に必要となる認(rèn)可コードグラントを?qū)g裝します

  1. 認(rèn)可サーバー

    プラットフォーム (google や github など) のいずれかにすることも、KeyCloak を使用して獨(dú)自のプラットフォームを作成することも、OAuth 2.0 標(biāo)準(zhǔn)に準(zhǔn)拠した獨(dú)自のプラットフォームを構(gòu)築することもできます (これは次のブログで行うかも知れません?)

  2. Spring Boot アプリケーション

    これは、コード交換、検証、ユーザー詳細(xì)の保存、JWT トークンの割り當(dāng)てなどのすべての操作を処理するメインのバックエンド アプリケーション/サービスになります

  3. React アプリケーション (フロントエンド)

    これは、認(rèn)可のためにユーザーを認(rèn)可サーバーにリダイレクトするクライアントになります。

つまり、私たちの実裝でやることは、フロントエンド(web/app)がバックエンドエンドポイントへのリダイレクトURIを使用してユーザーをGoogleログインにリダイレクトすることです。これによりさらに制御が行われます。これについては後で説明し、redirect_urlとともに説明します。また、アプリのクライアント ID も渡します。これらはすべてクエリ パラメーターで送信されます。

いいえ、ユーザーが Google に正常にログインすると、認(rèn)証サーバー (Google の) はリクエストをバックエンド エンドポイントにリダイレクトします。そこで私たちが行うことは、認(rèn)証サーバーと認(rèn)証コードを交換して、アクセス トークンとリフレッシュ トークンを取得することです。必要に応じて認(rèn)証を処理し、最後に、Cookie を含む応答をフロントエンドに送り返し、ダッシュボードまたは保護(hù)されたページにリダイレクトします。

ここでコードを調(diào)べますが、OAuth クライアントの Google コンソール ダッシュボードの承認(rèn)されたリダイレクト URL にバックエンド エンドポイントの URL を必ず追加してください。

* **CsrfFilter**: Validates CSRF tokens to prevent Cross-Site Request Forgery attacks.

* **CorsFilter**: Manages Cross-Origin Resource Sharing (CORS) rules for secure API access from different domains.

* **ExceptionTranslationFilter**: Handles security-related exceptions (e.g., invalid credentials) and sends appropriate responses to the client.

これで、これで問(wèn)題なく動(dòng)作します。テスト用に、コンテキストを持ち、ログインと登録の機(jī)能を知っているだけの単純なフロントエンド アプリケーションを作成できます。

ここまで読んでいただきありがとうございました。何かご提案がございましたら、コメント欄に書き込んでください

以上がSpring Security と OAuth についての詳細(xì)內(nèi)容です。詳細(xì)については、PHP 中國(guó)語(yǔ) Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當(dāng)する法的責(zé)任を負(fù)いません。盜作または侵害の疑いのあるコンテンツを見(jiàn)つけた場(chǎng)合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無(wú)料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

寫真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無(wú)料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡(jiǎn)単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無(wú)料のコードエディター

SublimeText3 中國(guó)語(yǔ)版

SublimeText3 中國(guó)語(yǔ)版

中國(guó)語(yǔ)版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強(qiáng)力な PHP 統(tǒng)合開(kāi)発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開(kāi)発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

ハッシュマップとハッシュテーブルの違いは? ハッシュマップとハッシュテーブルの違いは? Jun 24, 2025 pm 09:41 PM

ハッシュマップとハッシュテーブルの違いは、主にスレッドの安全性、ヌル価値のサポート、パフォーマンスに反映されます。 1.スレッドの安全性の観點(diǎn)から、ハッシュテーブルはスレッドセーフであり、その方法はほとんど同期メソッドであり、ハッシュマップはスレッドセーフではない同期処理を?qū)g行しません。 2。ヌル値のサポートに関しては、ハッシュマップは1つのnullキーと複數(shù)のヌル値を許可しますが、ハッシュテーブルはnullキーや値を許可しません。 3.パフォーマンスの観點(diǎn)から、ハッシュマップは同期メカニズムがないため、より効率的です。ハッシュテーブルは、各操作のロックパフォーマンスが低いです。代わりにconcurrenthashmapを使用することをお?jiǎng)幛幛筏蓼埂?/p>

なぜラッパークラスが必要なのですか? なぜラッパークラスが必要なのですか? Jun 28, 2025 am 01:01 AM

Javaは、基本的なデータ型がオブジェクト指向の操作に直接參加できないため、ラッパークラスを使用し、実際のニーズでオブジェクトフォームが必要になることが多いためです。 1.コレクションクラスは、リストが自動(dòng)ボクシングを使用して數(shù)値を保存するなど、オブジェクトのみを保存できます。 2。ジェネリックは基本的なタイプをサポートしておらず、パッケージングクラスはタイプパラメーターとして使用する必要があります。 3.パッケージングクラスは、null値を表して、データまたは欠落データを區(qū)別できます。 4.パッケージングクラスは、データの解析と処理を容易にするための文字列変換などの実用的な方法を提供するため、これらの特性が必要なシナリオでは、パッケージングクラスは不可欠です。

インターフェイスの靜的メソッドとは何ですか? インターフェイスの靜的メソッドとは何ですか? Jun 24, 2025 pm 10:57 PM

StaticMethodsinInterfaceswereIntroducatedinjava8toalowutilityは、interfaceitself.beforejava8、そのような導(dǎo)入のために導(dǎo)入されたコード、rediveTodisorgedCode.now、statecmethodssprovidreebenefits:1)彼らの可能性のある測(cè)定di

JITコンパイラはどのようにコードを最適化しますか? JITコンパイラはどのようにコードを最適化しますか? Jun 24, 2025 pm 10:45 PM

JITコンパイラは、メソッドインライン、ホットスポット検出とコンピレーション、タイプの投機(jī)と偏見(jiàn)、冗長(zhǎng)操作の排除の4つの方法を通じてコードを最適化します。 1。メソッドインラインで呼び出しのオーバーヘッドを減らし、頻繁に小さな方法と呼ばれる挿入をコールに直接直接挿入します。 2。ホットスポットの検出と高周波コードの実行とそれを中央に最適化して、リソースを節(jié)約します。 3。タイプ投機(jī)は、敬v的な呼び出しを達(dá)成するためにランタイムタイプ情報(bào)を収集し、効率を向上させます。 4.冗長(zhǎng)操作は、運(yùn)用データの削除に基づいて役に立たない計(jì)算と検査を排除し、パフォーマンスを向上させます。

インスタンスイニシャルイザーブロックとは何ですか? インスタンスイニシャルイザーブロックとは何ですか? Jun 25, 2025 pm 12:21 PM

インスタンス初期化ブロックは、Javaで使用され、コンストラクターの前に実行されるオブジェクトを作成するときに初期化ロジックを?qū)g行します。複數(shù)のコンストラクターが初期化コード、複雑なフィールド初期化、または匿名のクラス初期化シナリオを共有するシナリオに適しています。靜的初期化ブロックとは異なり、インスタンス化されるたびに実行されますが、靜的初期化ブロックはクラスがロードされたときに1回のみ実行されます。

変數(shù)の「ファイナル」キーワードは何ですか? 変數(shù)の「ファイナル」キーワードは何ですか? Jun 24, 2025 pm 07:29 PM

Injava、thefinalkeywordpreventsavariaibleのValue frombeingededafterassignment、ButiTsbehiviordiffersforprimitivesandobjectReferences

工場(chǎng)のパターンとは何ですか? 工場(chǎng)のパターンとは何ですか? Jun 24, 2025 pm 11:29 PM

ファクトリーモードは、オブジェクトの作成ロジックをカプセル化するために使用され、コードをより柔軟でメンテナンスしやすく、ゆるく結(jié)合します。コアの答えは、オブジェクトの作成ロジックを一元的に管理し、実裝の詳細(xì)を隠し、複數(shù)の関連オブジェクトの作成をサポートすることです。特定の説明は次のとおりです。工場(chǎng)モードは、NewClass()の使用を直接回避し、処理のための特別な工場(chǎng)クラスまたは方法にオブジェクトの作成を手渡します。複數(shù)のタイプの関連オブジェクトが作成され、作成ロジックが変更され、実裝の詳細(xì)を非表示にする必要があるシナリオに適しています。たとえば、支払いプロセッサでは、Stripe、PayPal、その他のインスタンスが工場(chǎng)を通じて作成されます。その実裝には、入力パラメーターに基づいて工場(chǎng)クラスによって返されるオブジェクトが含まれ、すべてのオブジェクトは共通のインターフェイスを?qū)g現(xiàn)します。一般的なバリアントには、単純な工場(chǎng)、工場(chǎng)法、抽象的な工場(chǎng)が含まれます。これらは異なる複雑さに適しています。

タイプキャストとは何ですか? タイプキャストとは何ですか? Jun 24, 2025 pm 11:09 PM

変換には、暗黙的で明示的な変換には2つのタイプがあります。 1.暗黙的な変換は、INTを2倍に変換するなど、自動(dòng)的に発生します。 2。明示的な変換には、(int)mydoubleの使用など、手動(dòng)操作が必要です。タイプ変換が必要な場(chǎng)合には、ユーザー入力の処理、數(shù)學(xué)操作、または関數(shù)間のさまざまなタイプの値の渡されます。注意する必要がある問(wèn)題は次のとおりです。浮動(dòng)小數(shù)點(diǎn)數(shù)を整數(shù)に変換すると、分?jǐn)?shù)部分が切り捨てられ、大きなタイプを小さなタイプに変えるとデータの損失につながる可能性があり、一部の言語(yǔ)では特定のタイプの直接変換ができません。言語(yǔ)変換ルールを適切に理解することは、エラーを回避するのに役立ちます。

See all articles