亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

ホームページ 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)固な基盤(pán)が得られます。


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ī)能を知っているだけの単純なフロントエンド アプリケーションを作成できます。

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

以上が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

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

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

寫(xiě)真から衣服を削除するオンライン 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)

Javaでは、CallableとRunnableの違い Javaでは、CallableとRunnableの違い Jul 04, 2025 am 02:50 AM

Javaでは、CallableとRunnableには3つの主な違いがあります。まず、呼び出し可能な方法は結(jié)果を返すことができます。これは、呼び出し可能などの値を返す必要があるタスクに適しています。 run()runnableメソッドには戻り値がありませんが、ロギングなど、返品する必要のないタスクに適しています。第二に、Callableは、エラーの送信を容易にするためにチェックされた例外をスローすることができます。 runnableは、內(nèi)部的に例外を処理する必要があります。第三に、runnableはスレッドまたはexecutorserviceに直接渡すことができますが、callableはexecutorserviceにのみ提出し、將來(lái)のオブジェクトをに返すことができます

現(xiàn)代のジャワの非同期プログラミング技術(shù) 現(xiàn)代のジャワの非同期プログラミング技術(shù) Jul 07, 2025 am 02:24 AM

Javaは、Java19での完了可能なストリーム(ProjectReactorなど)、仮想スレッドの使用など、非同期プログラミングをサポートしています。 1.CompletableFutureチェーンコールを通じてコードの読みやすさとメンテナンスを改善し、タスクオーケストレーションと例外処理をサポートします。 2。ProjectReactorは、バックプレッシャーメカニズムとリッチ演算子を備えた応答性プログラミングを?qū)g裝するためのモノとフラックスタイプを提供します。 3.仮想スレッドは、同時(shí)性コストを削減し、I/O集約型タスクに適しており、従來(lái)のプラットフォームスレッドよりも軽量で拡張が容易です。各方法には適用可能なシナリオがあり、適切なツールをお客様のニーズに応じて選択する必要があり、混合モデルはシンプルさを維持するために避ける必要があります

Java Nioとその利點(diǎn)を理解する Java Nioとその利點(diǎn)を理解する Jul 08, 2025 am 02:55 AM

Javanioは、Java 1.4によって導(dǎo)入された新しいIoapiです。 1)バッファとチャネルを?qū)澫螭趣筏皮い蓼埂?)バッファ、チャネル、セレクターのコアコンポーネント、3)ノンブロッキングモードをサポートし、4)従來(lái)のIOよりも効率的に並行接続を処理します。その利點(diǎn)は、次のことに反映されます。1)非ブロッキングIOはスレッドオーバーヘッドを減らし、2)データ送信効率を改善し、3)セレクターがマルチプレックスを?qū)g現(xiàn)し、4)メモリマッピングはファイルの読み取りと書(shū)き込みを速めます。注:1)バッファのフリップ/クリア操作は混亂しやすく、2)不完全なデータをブロックせずに手動(dòng)で処理する必要があります。3)セレクター登録は時(shí)間內(nèi)にキャンセルする必要があります。4)NIOはすべてのシナリオに適していません。

Javaで酵素を使用するためのベストプラクティス Javaで酵素を使用するためのベストプラクティス Jul 07, 2025 am 02:35 AM

Javaでは、列挙は固定定數(shù)セットを表すのに適しています。ベストプラクティスには以下が含まれます。1。列挙を使用して固定狀態(tài)またはオプションを表して、タイプの安全性と読みやすさを改善します。 2.フィールド、コンストラクター、ヘルパーメソッドなどの定義など、柔軟性を高めるために、酵素にプロパティとメソッドを追加します。 3. enummapとEnumsetを使用して、パフォーマンスとタイプの安全性を向上させ、配列に??基づいてより効率的であるためです。 4.動(dòng)的値、頻繁な変更、複雑なロジックシナリオなどの列挙の悪用を避けてください。これらは他の方法に置き換える必要があります。列挙の正しい使用は、コードの品質(zhì)を改善し、エラーを減らすことができますが、適用される境界に注意を払う必要があります。

Java Classloadersの動(dòng)作方法 Java Classloadersの動(dòng)作方法 Jul 06, 2025 am 02:53 AM

Javaのクラスロードメカニズムはクラスローダーを介して実裝されており、そのコアワークフローは、読み込み、リンク、初期化の3つの段階に分けられます。ローディングフェーズ中、クラスローダーはクラスのバイトコードを動(dòng)的に読み取り、クラスオブジェクトを作成します。リンクには、クラスの正しさの確認(rèn)、靜的変數(shù)へのメモリの割り當(dāng)て、およびシンボル?yún)⒄栅谓馕訾蓼欷蓼?。初期化は、靜的コードブロックと靜的変數(shù)割り當(dāng)てを?qū)g行します。クラスの読み込みは、親クラスローダーに優(yōu)先順位を付けてクラスを見(jiàn)つけ、ブートストラップ、拡張機(jī)能、およびアプリケーションクラスローダーを順?lè)嗽嚖筏啤ⅴ偿ⅴ楗攻楗ぅ芝楗辘踩扦ⅳ?、重複した負(fù)荷を回避することを確認(rèn)します。開(kāi)発者は、urlclasslなどのクラスローダーをカスタマイズできます

Javaのさまざまな同期メカニズムの調(diào)査 Javaのさまざまな同期メカニズムの調(diào)査 Jul 04, 2025 am 02:53 AM

JavaprovidesMultipLesynchronizationStoolsforthreadsafety.1.synchronizedBlocksensurexclusionbyLockingmethodsorspeficCodeSections.2.ReentrantLockOfferSollol、TryLockandFairnessPolicies.3.ConditionVarisallowthReadStowaitfor

一般的なJava例外を効果的に処理します 一般的なJava例外を効果的に処理します Jul 05, 2025 am 02:35 AM

Java例外処理の鍵は、チェックされた例外と未確認(rèn)の例外を區(qū)別し、最後に合理的にログを記録するTry-Catchを使用することです。 1. IOExceptionなどのチェックされた例外は、予想される外部問(wèn)題に適した処理を強(qiáng)制される必要があります。 2。nullpointerexceptionなどのチェックされていない例外は、通常、プログラムロジックエラーによって引き起こされ、ランタイムエラーです。 3。例外をキャッチする場(chǎng)合、例外の一般的なキャプチャを避けるために、それらは具體的かつ明確でなければなりません。 4.リソース付きのTry-Resourcesを使用して、コードの手動(dòng)清掃を減らすためにリソースを自動(dòng)的に閉鎖することをお?jiǎng)幛幛筏蓼埂?5。例外処理では、詳細(xì)情報(bào)をログフレームワークと組み合わせて記録して後で容易にする必要があります

ハッシュマップはJavaで內(nèi)部的にどのように機(jī)能しますか? ハッシュマップはJavaで內(nèi)部的にどのように機(jī)能しますか? Jul 15, 2025 am 03:10 AM

HashMapは、Javaのハッシュテーブルを介してキーと値のペアストレージを?qū)g裝し、そのコアはデータの位置をすばやく配置することにあります。 1.最初にキーのHashCode()メソッドを使用して、ハッシュ値を生成し、ビット操作を介して配列インデックスに変換します。 2。異なるオブジェクトは、同じハッシュ値を生成し、競(jìng)合をもたらす場(chǎng)合があります。この時(shí)點(diǎn)で、ノードはリンクされたリストの形式で取り付けられています。 JDK8の後、リンクされたリストが長(zhǎng)すぎ(デフォルトの長(zhǎng)さ8)、効率を改善するために赤と黒の木に変換されます。 3.カスタムクラスをキーとして使用する場(chǎng)合、equals()およびhashcode()メソッドを書(shū)き直す必要があります。 4。ハッシュマップは容量を動(dòng)的に拡大します。要素の數(shù)が容量を超え、負(fù)荷係數(shù)(デフォルト0.75)を掛けた場(chǎng)合、拡張して再ハッシュします。 5。ハッシュマップはスレッドセーフではなく、マルチスレッドでconcuを使用する必要があります

See all articles