<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 沧海月明Z有泪</title>
    <description>The latest articles on DEV Community by 沧海月明Z有泪 (@z98743660).</description>
    <link>https://dev.to/z98743660</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2909836%2Ff061d71f-4932-44ea-8c8d-34784a4b5909.png</url>
      <title>DEV Community: 沧海月明Z有泪</title>
      <link>https://dev.to/z98743660</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/z98743660"/>
    <language>en</language>
    <item>
      <title>User Management System Based on Spring Cloud Gateway + RBAC: Permission Authentication and Global Validation</title>
      <dc:creator>沧海月明Z有泪</dc:creator>
      <pubDate>Mon, 10 Mar 2025 00:51:18 +0000</pubDate>
      <link>https://dev.to/z98743660/user-management-system-based-on-spring-cloud-gateway-rbac-permission-authentication-and-global-mdn</link>
      <guid>https://dev.to/z98743660/user-management-system-based-on-spring-cloud-gateway-rbac-permission-authentication-and-global-mdn</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In modern microservice architectures, the user management system is one of the core components, responsible for user authentication and permission management. As the scale of the system grows, efficiently managing user permissions and ensuring system security has become a significant challenge. A user management system based on Spring Cloud Gateway and RBAC (Role-Based Access Control) can effectively address this issue. This article will introduce how to implement permission authentication and global validation using Spring Cloud Gateway, and how to build a secure user management system by integrating the RBAC model.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Introduction to Spring Cloud Gateway
&lt;/h3&gt;

&lt;p&gt;Spring Cloud Gateway is an API gateway within the Spring Cloud ecosystem, designed to provide a simple and effective way to route requests, perform authentication, and implement load balancing for microservice architectures. Built on top of Spring 6 and Spring Boot 3, it supports asynchronous non-blocking request handling, making it suitable for high-concurrency scenarios.&lt;/p&gt;

&lt;p&gt;The core features of Spring Cloud Gateway include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Routing&lt;/strong&gt;: Requests are routed to different microservices based on path, method, headers, and other criteria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filters&lt;/strong&gt;: Logic can be executed before or after requests reach the target service, such as permission validation and request logging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing&lt;/strong&gt;: Integrated with Spring Cloud LoadBalancer to distribute requests across services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit Breaker&lt;/strong&gt;: Combined with Spring Cloud CircuitBreaker to provide service resilience and fallback mechanisms.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. RBAC (Role-Based Access Control) Model
&lt;/h3&gt;

&lt;p&gt;RBAC is a widely-used permission management model that associates permissions with roles, and users gain permissions through role assignments. The core concepts of RBAC include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User&lt;/strong&gt;: The system's end-user, which can be an individual or an application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role&lt;/strong&gt;: A collection of permissions that users inherit when assigned to them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission&lt;/strong&gt;: The ability to perform specific actions on system resources, such as "read," "write," or "delete."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The advantages of RBAC include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Permissions can be easily managed by assigning or revoking roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Centralizing permission management at the role level reduces the complexity of directly managing user permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Hierarchical roles and permission inheritance enhance system security.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Permission Authentication and Global Validation with Spring Cloud Gateway
&lt;/h3&gt;

&lt;p&gt;In microservice architectures, the API gateway serves as the entry point for all external requests. Therefore, it is appropriate to place permission authentication and global validation logic at the gateway level. Spring Cloud Gateway's powerful filter mechanism allows for permission validation before requests reach the target service.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.1 Permission Authentication Process
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Login&lt;/strong&gt;: Users submit their username and password through a login interface. After verifying the user's identity, the system generates a JWT (JSON Web Token) and returns it to the client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token in Requests&lt;/strong&gt;: The client includes the JWT in subsequent requests, typically in the &lt;code&gt;Authorization&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gateway Token Validation&lt;/strong&gt;: Upon receiving a request, Spring Cloud Gateway first validates the JWT through a custom global filter. If the token is invalid or expired, the gateway returns a 401 Unauthorized error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission Validation&lt;/strong&gt;: After the token is validated, the gateway checks whether the user has the necessary permissions based on their role and the requested path. If not, a 403 Forbidden error is returned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routing to Target Service&lt;/strong&gt;: If permission validation passes, the request is routed to the target microservice.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  3.2 Implementation of Global Validation
&lt;/h4&gt;

&lt;p&gt;Global validation in Spring Cloud Gateway can be implemented through a custom &lt;code&gt;GlobalFilter&lt;/code&gt;. Here is a simple example of a global validation filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GlobalGatewayFilter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;GlobalFilter&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Ordered&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;AuthProperties&lt;/span&gt; &lt;span class="n"&gt;authProperties&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;JwtUtils&lt;/span&gt; &lt;span class="n"&gt;jwtUtils&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;RedisUtils&lt;/span&gt; &lt;span class="n"&gt;redisUtils&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Token Filter
     *
     * @param exchange exchange
     * @param chain    chain
     * @return Mono
     */&lt;/span&gt;
    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;u003cVoid&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;u003e&lt;/span&gt; &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ServerWebExchange&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;GatewayFilterChain&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;ServerHttpRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRequest&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getToken&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;DecodedJWT&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwtUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;verifyJwt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;TokenExpiredException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;unauthorized&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResponse&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"token is expired."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JWTVerificationException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;unauthorized&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResponse&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"token verification failed."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;unauthorized&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResponse&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"token is not legal."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;verifyAuthorization&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMethod&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;unauthorized&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResponse&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"request access denied, may be unauthorized."&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Set username in request header&lt;/span&gt;
        &lt;span class="nc"&gt;ServerHttpRequest&lt;/span&gt; &lt;span class="n"&gt;newRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mutate&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-Forwarded-For"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newHeader&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SystemConstant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HEADER_AUTHORIZATION&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;USERNAME&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTH_WAREHOUSE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mutate&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newRequest&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;AuthFilter&lt;/code&gt; first retrieves the JWT from the request header and validates its authenticity. If the token is invalid, a 401 error is returned. If valid, the filter extracts the user's role from the token and checks whether the user has permission to access the requested resource based on the request path. If permission is denied, a 403 error is returned. If validation passes, the request continues down the filter chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource Access Permission Validation Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="nf"&gt;verifyAuthorization&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DecodedJWT&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpMethod&lt;/span&gt; &lt;span class="n"&gt;httpMethod&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;JWTVerificationException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Claim&lt;/span&gt; &lt;span class="n"&gt;authorities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClaim&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AUTH_MENUS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;authorities&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;u003cString&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;u003e&lt;/span&gt; &lt;span class="n"&gt;authoritySet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;authorities&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CollectionUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authoritySet&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authoritySet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SUPPER_PERMISSION&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpMethod&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;requestUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;authoritySet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;anyMatch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;url:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;startsWith&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;\u003e Here, &lt;strong&gt;Claim authorities = jwt.getClaim(AuthConstants.AUTH_MENUS)&lt;/strong&gt;, we store user permissions in the token and then retrieve them from the token. However, if the user's permissions are extensive, the token may become too large and impact performance. In such cases, alternative methods should be considered, such as querying user permissions from the &lt;strong&gt;User Management Service&lt;/strong&gt; and caching them. This way, the token only needs to store user role information.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.3 RBAC Permission Management
&lt;/h4&gt;

&lt;p&gt;In the RBAC model, permission management is typically implemented through a database. Here is a simple database schema for permission management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User Table&lt;/strong&gt;: Stores basic user information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role Table&lt;/strong&gt;: Stores basic role information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission Table&lt;/strong&gt;: Stores basic permission information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UserRole Table&lt;/strong&gt;: Associates users with roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RolePermission Table&lt;/strong&gt;: Associates roles with permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these tables, flexible management of users, roles, and permissions can be achieved. During permission validation, the system queries the permissions associated with the user's role and determines whether access to the requested resource is allowed.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.4 User Login
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;User Login Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/signin"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;AuthModel&lt;/span&gt; &lt;span class="nf"&gt;authenticateUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Valid&lt;/span&gt; &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;LoginRequest&lt;/span&gt; &lt;span class="n"&gt;loginRequest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Authentication&lt;/span&gt; &lt;span class="n"&gt;authentication&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;authenticationManager&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authenticate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UsernamePasswordAuthenticationToken&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loginRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUsername&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;loginRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPassword&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;

    &lt;span class="nc"&gt;TokenResponse&lt;/span&gt; &lt;span class="n"&gt;tokenResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwtUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateJwtCookie&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authorities&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userDetails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUsername&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;authWarehouseCodes&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;userDetails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getTenantName&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="nc"&gt;UserModel&lt;/span&gt; &lt;span class="n"&gt;userModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userDetails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userDetails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUsername&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userDetails&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getAvatar&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AuthModel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getToken&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userModel&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExpiresIn&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Token Generation Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;generateToken&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;authorityList&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;authWarehouseCodes&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;tenantName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Algorithm&lt;/span&gt; &lt;span class="n"&gt;algorithm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Algorithm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;HMAC256&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenSecret&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;JWT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withClaim&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AuthConstants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;USERNAME&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withClaim&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;AUTH_MENUS&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authorityList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withExpiresAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tokenExpiration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000L&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sign&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;algorithm&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Conclusion
&lt;/h3&gt;

&lt;p&gt;A user management system based on Spring Cloud Gateway and RBAC can effectively implement permission authentication and global validation. By placing permission validation logic at the gateway level, repetitive code in each microservice can be reduced, enhancing system security and maintainability. The integration of the RBAC model makes permission management more flexible and controllable. In practical projects, this solution can be further expanded and optimized to meet complex permission management requirements.&lt;/p&gt;

&lt;p&gt;Through this article, we hope readers can understand how to build a secure user management system using Spring Cloud Gateway and RBAC, and apply these technologies in their projects.&lt;/p&gt;

&lt;p&gt;The code is available on GitHub: &lt;a href="https://github.com/jingsewu/open-wes" rel="noopener noreferrer"&gt;GitHub - jingsewu/open-wes&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>microservices</category>
      <category>springcloud</category>
    </item>
    <item>
      <title>Integrate SpringAI with DeepSeek</title>
      <dc:creator>沧海月明Z有泪</dc:creator>
      <pubDate>Mon, 10 Mar 2025 00:50:23 +0000</pubDate>
      <link>https://dev.to/z98743660/integrate-springai-with-deepseek-30e8</link>
      <guid>https://dev.to/z98743660/integrate-springai-with-deepseek-30e8</guid>
      <description>&lt;p&gt;As businesses increasingly rely on advanced data analytics and machine learning for decision-making, integrating&lt;br&gt;
powerful AI models into existing systems becomes essential. One such powerful integration is combining &lt;strong&gt;Spring AI&lt;/strong&gt;, a&lt;br&gt;
framework for building AI-powered applications with Spring, with &lt;strong&gt;DeepSeek&lt;/strong&gt;, a large language model.&lt;/p&gt;

&lt;p&gt;In this post, we’ll walk through the integration of Spring AI with DeepSeek, explaining the key concepts, benefits, and&lt;br&gt;
a step-by-step guide on how to make this integration work seamlessly.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Spring AI?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://spring.io/projects/spring-ai" rel="noopener noreferrer"&gt;Spring AI&lt;/a&gt; is a framework that allows developers to create AI applications with&lt;br&gt;
the power and flexibility of the Spring ecosystem. It provides the tools and capabilities to integrate large language&lt;br&gt;
models into Spring-based applications, making it easier for developers to build and deploy AI-powered solutions without&lt;br&gt;
the steep learning curve.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Integrate Spring AI with DeepSeek?
&lt;/h3&gt;

&lt;p&gt;Combining Spring AI with DeepSeek opens up a world of possibilities for your application, allowing you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access to Advanced Language Models&lt;/strong&gt;: Integrate DeepSeek's state-of-the-art models into your Spring-based&lt;br&gt;
applications, enhancing natural language understanding and generation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-Time AI Responses&lt;/strong&gt;: Combine DeepSeek's powerful AI models with Spring's backend services to deliver&lt;br&gt;
intelligent, real-time responses within your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalable AI Solutions&lt;/strong&gt;: Build AI systems that scale with your business needs using Spring’s robust infrastructure&lt;br&gt;
and DeepSeek’s advanced language models.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before diving into the integration process, ensure you have the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spring Boot&lt;/strong&gt;: A running Spring Boot application, as Spring AI is built on top of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepSeek API Key&lt;/strong&gt;: Access to DeepSeek’s API for leveraging its models and services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java 17+&lt;/strong&gt;: Since Spring AI works best with Java 17 and higher.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Step-by-Step Integration Guide
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Step 1: Set up Your Spring Boot Application
&lt;/h4&gt;

&lt;p&gt;If you don’t have a Spring Boot application set up already, you can create one using the &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;Spring Initializr&lt;/a&gt;. Select&lt;br&gt;
dependencies such as &lt;strong&gt;Spring Web&lt;/strong&gt;, &lt;strong&gt;Spring Boot DevTools&lt;/strong&gt;, and &lt;strong&gt;Spring AI&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://start.spring.io/starter.zip -d dependencies=web,devtools -d name=SpringDeepSeek -o SpringDeepSeek.zip` 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Add Dependencies
&lt;/h4&gt;

&lt;p&gt;In your &lt;code&gt;build.gradle&lt;/code&gt; file, add the necessary dependencies for Spring AI and DeepSeek. For Spring AI, &lt;br&gt;
use the &lt;code&gt;spring-ai-openai-spring-boot-starter&lt;/code&gt; dependency. Since Spring AI doesn’t have a specific client for DeepSeek, &lt;br&gt;
you can interact with OpenAI API directly.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Configure DeepSeek API
&lt;/h4&gt;

&lt;p&gt;To interact with DeepSeek, you’ll need an API key. Add your key to &lt;code&gt;application.properties&lt;/code&gt; or &lt;code&gt;application.yml&lt;/code&gt; for&lt;br&gt;
secure access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  ai:
    openai:
      base-url: https://api.deepseek.com 
      api-key: xxx
      chat:
        options:
          model: deepseek-chat
          temperature: 0    
      embedding:
        enabled: false      
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Implement DeepSeek Integration
&lt;/h4&gt;

&lt;p&gt;Create a service that interacts with DeepSeek’s API to retrieve data insights&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class AiChatService {

    private final ChatModel chatModel;

    private Flux&amp;lt;String&amp;gt; executeAI(String message, String conversationId, PromptTemplate template) {

        String relevantHistory = chatMemory.get(conversationId, 10)
                .stream()
                .map(this::formatMessage)
                .collect(Collectors.joining("\n"));

        // Add context to template
        template.add("context", relevantHistory);

        chatMemory.add(conversationId, new UserMessage(message));

        // Create a StringBuilder to accumulate the response
        StringBuilder fullResponse = new StringBuilder();

        return this.chatModel.stream(template.createMessage()).map(chunk -&amp;gt; {
            fullResponse.append(chunk);
            return chunk;
        }).doOnComplete(() -&amp;gt; {
            // Only save to chat memory once we have the complete response
            chatMemory.add(conversationId, new AssistantMessage(fullResponse.toString()));
        });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5: Combine Spring AI and DeepSeek
&lt;/h4&gt;

&lt;p&gt;Now, combine both services to allow your application to use the insights from DeepSeek and apply them to your AI model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RequestMapping("/ai")
public class AIController {

    @GetMapping("chat")
    public Flux&amp;lt;String&amp;gt; chat(@RequestParam(value = "message") String message) {
        String currentUser = UserContext.getCurrentUser();
        return aiService.chat(message, currentUser);
    }

    @PostMapping("analysis")
    @CrossOrigin
    public AnalysisResult sqlAnalysis(@RequestBody AnalysisQueryVO analysisQueryVO) throws SQLException {
        String currentUser = UserContext.getCurrentUser();
        return aiService.analysis(analysisQueryVO.getQuery(), currentUser);
    }

    @PostMapping("generateJsFunction")
    @CrossOrigin
    public Flux&amp;lt;String&amp;gt; generateJsFunction(@RequestBody JsFunctionGenerationRequest jsFunctionGenerationRequest) {
        String currentUser = UserContext.getCurrentUser();
        return aiService.generateJsFunction(jsFunctionGenerationRequest, currentUser);
    }

    @PostMapping("generateCode")
    @CrossOrigin
    public Flux&amp;lt;String&amp;gt; generateCode(@RequestBody CodeGenerationRequest codeGenerationRequest) {
        String currentUser = UserContext.getCurrentUser();
        return aiService.generateCode(codeGenerationRequest, currentUser);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 6: Test the Integration
&lt;/h4&gt;

&lt;p&gt;Start your Spring Boot application and test the integration by calling the API endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl "http://localhost:8080/ai/chat?message=some_data_to_analyze"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive a response that includes data from DeepSeek and the analysis from your AI model.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 7: Some Use cases
&lt;/h4&gt;

&lt;h6&gt;
  
  
  AI Assistance:
&lt;/h6&gt;

&lt;p&gt;AI Assistance uses AI models to provide automated, real-time responses or insights based on user input. It helps users by answering queries, offering suggestions, or assisting with tasks, enhancing efficiency in applications like customer support or virtual assistants.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frksu7vkh55q2yc4ueatw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frksu7vkh55q2yc4ueatw.png" alt="Image description" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  AI Data Analysis
&lt;/h6&gt;

&lt;p&gt;AI Data Analysis enables AI models to process and extract insights from large datasets. It identifies patterns and trends, aiding data-driven decision-making. This is crucial for applications where analyzing data quickly and accurately leads to better business outcomes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgd2lbmx6ti614ye0bia8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgd2lbmx6ti614ye0bia8.png" alt="Image description" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Integrating &lt;strong&gt;Spring AI&lt;/strong&gt; with &lt;strong&gt;DeepSeek&lt;/strong&gt; offers a robust solution for building AI-powered applications that can&lt;br&gt;
analyze large datasets, make real-time decisions, and scale with your business needs. With this setup, you can harness&lt;br&gt;
the power of deep learning and machine learning to improve your warehouse execution system or any other data-driven&lt;br&gt;
application.&lt;/p&gt;

&lt;p&gt;You can explore the project further at &lt;a href="https://github.com/jingsewu/open-wes" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and find more information in the &lt;strong&gt;modules-ai&lt;/strong&gt; section.&lt;/p&gt;

&lt;p&gt;Feel free to customize the steps and models used according to your project’s specific requirements.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>webdev</category>
      <category>spring</category>
    </item>
    <item>
      <title>Integrate SpringAI with DeepSeek</title>
      <dc:creator>沧海月明Z有泪</dc:creator>
      <pubDate>Mon, 10 Mar 2025 00:50:23 +0000</pubDate>
      <link>https://dev.to/z98743660/integrate-springai-with-deepseek-4g44</link>
      <guid>https://dev.to/z98743660/integrate-springai-with-deepseek-4g44</guid>
      <description>&lt;p&gt;As businesses increasingly rely on advanced data analytics and machine learning for decision-making, integrating&lt;br&gt;
powerful AI models into existing systems becomes essential. One such powerful integration is combining &lt;strong&gt;Spring AI&lt;/strong&gt;, a&lt;br&gt;
framework for building AI-powered applications with Spring, with &lt;strong&gt;DeepSeek&lt;/strong&gt;, a large language model.&lt;/p&gt;

&lt;p&gt;In this post, we’ll walk through the integration of Spring AI with DeepSeek, explaining the key concepts, benefits, and&lt;br&gt;
a step-by-step guide on how to make this integration work seamlessly.&lt;/p&gt;
&lt;h3&gt;
  
  
  What is Spring AI?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://spring.io/projects/spring-ai" rel="noopener noreferrer"&gt;Spring AI&lt;/a&gt; is a framework that allows developers to create AI applications with&lt;br&gt;
the power and flexibility of the Spring ecosystem. It provides the tools and capabilities to integrate large language&lt;br&gt;
models into Spring-based applications, making it easier for developers to build and deploy AI-powered solutions without&lt;br&gt;
the steep learning curve.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Integrate Spring AI with DeepSeek?
&lt;/h3&gt;

&lt;p&gt;Combining Spring AI with DeepSeek opens up a world of possibilities for your application, allowing you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access to Advanced Language Models&lt;/strong&gt;: Integrate DeepSeek's state-of-the-art models into your Spring-based&lt;br&gt;
applications, enhancing natural language understanding and generation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-Time AI Responses&lt;/strong&gt;: Combine DeepSeek's powerful AI models with Spring's backend services to deliver&lt;br&gt;
intelligent, real-time responses within your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalable AI Solutions&lt;/strong&gt;: Build AI systems that scale with your business needs using Spring’s robust infrastructure&lt;br&gt;
and DeepSeek’s advanced language models.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;p&gt;Before diving into the integration process, ensure you have the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spring Boot&lt;/strong&gt;: A running Spring Boot application, as Spring AI is built on top of it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DeepSeek API Key&lt;/strong&gt;: Access to DeepSeek’s API for leveraging its models and services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java 17+&lt;/strong&gt;: Since Spring AI works best with Java 17 and higher.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Step-by-Step Integration Guide
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Step 1: Set up Your Spring Boot Application
&lt;/h4&gt;

&lt;p&gt;If you don’t have a Spring Boot application set up already, you can create one using the &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;Spring Initializr&lt;/a&gt;. Select&lt;br&gt;
dependencies such as &lt;strong&gt;Spring Web&lt;/strong&gt;, &lt;strong&gt;Spring Boot DevTools&lt;/strong&gt;, and &lt;strong&gt;Spring AI&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://start.spring.io/starter.zip -d dependencies=web,devtools -d name=SpringDeepSeek -o SpringDeepSeek.zip` 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 2: Add Dependencies
&lt;/h4&gt;

&lt;p&gt;In your &lt;code&gt;build.gradle&lt;/code&gt; file, add the necessary dependencies for Spring AI and DeepSeek. For Spring AI, &lt;br&gt;
use the &lt;code&gt;spring-ai-openai-spring-boot-starter&lt;/code&gt; dependency. Since Spring AI doesn’t have a specific client for DeepSeek, &lt;br&gt;
you can interact with OpenAI API directly.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter'

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 3: Configure DeepSeek API
&lt;/h4&gt;

&lt;p&gt;To interact with DeepSeek, you’ll need an API key. Add your key to &lt;code&gt;application.properties&lt;/code&gt; or &lt;code&gt;application.yml&lt;/code&gt; for&lt;br&gt;
secure access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  ai:
    openai:
      base-url: https://api.deepseek.com 
      api-key: xxx
      chat:
        options:
          model: deepseek-chat
          temperature: 0    
      embedding:
        enabled: false      
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Implement DeepSeek Integration
&lt;/h4&gt;

&lt;p&gt;Create a service that interacts with DeepSeek’s API to retrieve data insights&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class AiChatService {

    private final ChatModel chatModel;

    private Flux&amp;lt;String&amp;gt; executeAI(String message, String conversationId, PromptTemplate template) {

        String relevantHistory = chatMemory.get(conversationId, 10)
                .stream()
                .map(this::formatMessage)
                .collect(Collectors.joining("\n"));

        // Add context to template
        template.add("context", relevantHistory);

        chatMemory.add(conversationId, new UserMessage(message));

        // Create a StringBuilder to accumulate the response
        StringBuilder fullResponse = new StringBuilder();

        return this.chatModel.stream(template.createMessage()).map(chunk -&amp;gt; {
            fullResponse.append(chunk);
            return chunk;
        }).doOnComplete(() -&amp;gt; {
            // Only save to chat memory once we have the complete response
            chatMemory.add(conversationId, new AssistantMessage(fullResponse.toString()));
        });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 5: Combine Spring AI and DeepSeek
&lt;/h4&gt;

&lt;p&gt;Now, combine both services to allow your application to use the insights from DeepSeek and apply them to your AI model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RequestMapping("/ai")
public class AIController {

    @GetMapping("chat")
    public Flux&amp;lt;String&amp;gt; chat(@RequestParam(value = "message") String message) {
        String currentUser = UserContext.getCurrentUser();
        return aiService.chat(message, currentUser);
    }

    @PostMapping("analysis")
    @CrossOrigin
    public AnalysisResult sqlAnalysis(@RequestBody AnalysisQueryVO analysisQueryVO) throws SQLException {
        String currentUser = UserContext.getCurrentUser();
        return aiService.analysis(analysisQueryVO.getQuery(), currentUser);
    }

    @PostMapping("generateJsFunction")
    @CrossOrigin
    public Flux&amp;lt;String&amp;gt; generateJsFunction(@RequestBody JsFunctionGenerationRequest jsFunctionGenerationRequest) {
        String currentUser = UserContext.getCurrentUser();
        return aiService.generateJsFunction(jsFunctionGenerationRequest, currentUser);
    }

    @PostMapping("generateCode")
    @CrossOrigin
    public Flux&amp;lt;String&amp;gt; generateCode(@RequestBody CodeGenerationRequest codeGenerationRequest) {
        String currentUser = UserContext.getCurrentUser();
        return aiService.generateCode(codeGenerationRequest, currentUser);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 6: Test the Integration
&lt;/h4&gt;

&lt;p&gt;Start your Spring Boot application and test the integration by calling the API endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl "http://localhost:8080/ai/chat?message=some_data_to_analyze"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive a response that includes data from DeepSeek and the analysis from your AI model.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 7: Some Use cases
&lt;/h4&gt;

&lt;h6&gt;
  
  
  AI Assistance:
&lt;/h6&gt;

&lt;p&gt;AI Assistance uses AI models to provide automated, real-time responses or insights based on user input. It helps users by answering queries, offering suggestions, or assisting with tasks, enhancing efficiency in applications like customer support or virtual assistants.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frksu7vkh55q2yc4ueatw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frksu7vkh55q2yc4ueatw.png" alt="Image description" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  AI Data Analysis
&lt;/h6&gt;

&lt;p&gt;AI Data Analysis enables AI models to process and extract insights from large datasets. It identifies patterns and trends, aiding data-driven decision-making. This is crucial for applications where analyzing data quickly and accurately leads to better business outcomes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgd2lbmx6ti614ye0bia8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgd2lbmx6ti614ye0bia8.png" alt="Image description" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Integrating &lt;strong&gt;Spring AI&lt;/strong&gt; with &lt;strong&gt;DeepSeek&lt;/strong&gt; offers a robust solution for building AI-powered applications that can&lt;br&gt;
analyze large datasets, make real-time decisions, and scale with your business needs. With this setup, you can harness&lt;br&gt;
the power of deep learning and machine learning to improve your warehouse execution system or any other data-driven&lt;br&gt;
application.&lt;/p&gt;

&lt;p&gt;You can explore the project further at &lt;a href="https://github.com/jingsewu/open-wes" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and find more information in the &lt;strong&gt;modules-ai&lt;/strong&gt; section.&lt;/p&gt;

&lt;p&gt;Feel free to customize the steps and models used according to your project’s specific requirements.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>webdev</category>
      <category>spring</category>
    </item>
    <item>
      <title>Implement a Natural Language System Configuration Manager with Spring AI</title>
      <dc:creator>沧海月明Z有泪</dc:creator>
      <pubDate>Fri, 07 Mar 2025 01:15:36 +0000</pubDate>
      <link>https://dev.to/z98743660/implement-a-natural-language-system-configuration-manager-with-spring-ai-3dpc</link>
      <guid>https://dev.to/z98743660/implement-a-natural-language-system-configuration-manager-with-spring-ai-3dpc</guid>
      <description>&lt;p&gt;System configuration management is typically handled through configuration files, environment variables, or admin interfaces. But what if we could change system settings simply by chatting with our application? In this article, I'll show you how to build a chatbot that can understand and modify system configurations using natural language, powered by Spring AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Power of Natural Language Configuration
&lt;/h2&gt;

&lt;p&gt;Traditional configuration management requires users to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Know exact parameter names and valid values&lt;/li&gt;
&lt;li&gt;Navigate through configuration files or interfaces&lt;/li&gt;
&lt;li&gt;Understand technical syntax and formatting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using natural language processing, we can make this process more intuitive. Users can simply say things like "increase the connection timeout to 30 seconds" or "enable debug logging for the authentication module."&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Setting Up Spring AI
&lt;/h3&gt;

&lt;p&gt;look the article: &lt;a href="//./2025-02-14-Integrate-SpringAI-with-DeepSeek.md"&gt;Integrate-SpringAI-with-DeepSeek&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining Tool Functions
&lt;/h3&gt;

&lt;p&gt;Spring AI supports tool functions that allow the AI model to take specific actions. We'll define functions for reading and updating configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="nd"&gt;@RequiredArgsConstructor&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SystemConfigTool&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ITool&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ISystemConfigApi&lt;/span&gt; &lt;span class="n"&gt;systemConfigApi&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Tool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"getSystemConfig"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Retrieves the current system configuration settings, including basic, EMS, inbound, outbound, stock, and algorithm configurations. The returned {@link SystemConfigDTO} provides a comprehensive snapshot of all configurable system parameters."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SystemConfigDTO&lt;/span&gt; &lt;span class="nf"&gt;getSystemConfig&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;systemConfigApi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSystemConfig&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Tool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"updateSystemConfig"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""
            update System configuration settings，using JSON structure below：
            {
              "basicConfig": {
                "transferContainerReleaseMethod": "AUTOMATED|MANUAL",  
                "autoReleaseDelayTimeMin": number                      
              },
              "inboundConfig": {
                "checkRepeatedCustomerOrderNo": boolean,  
                "checkRepeatedLpnCode": boolean          
              },
              "outboundConfig": {
                "checkRepeatedCustomerOrderNo": boolean   
              },
              "stockConfig": {
                "stockAbnormalAutoCreateAdjustmentOrder": boolean,  
                "zeroStockSavedDays": number                        
              },
              "emsConfig": {
                "allowBatchCreateContainerTasks": boolean           
              },
              "outboundAlgoConfig": {
                "useLocalAlgorithm": boolean,        
                "cutoffTime": number,                
                "mode": "string",                    
                "orderDispatchStrategy": "string"    
              }
            }
            Example:
            - "Disable duplicate order check for inbound orders" → {"inboundConfig":{"checkRepeatedCustomerOrderNo":false}}
            - "Set zero stock retention period to 3 days" → {"stockConfig":{"zeroStockSavedDays":3}}
            - "Modify container release method and algorithm timeout simultaneously" → {
                             "basicConfig":{"transferContainerReleaseMethod":"MANUAL"},
                                "outboundAlgoConfig":{"cutoffTime":5000}
                            }
            """&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;updateSystemConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@ToolParam&lt;/span&gt; &lt;span class="nc"&gt;SystemConfigDTO&lt;/span&gt; &lt;span class="n"&gt;systemConfigDTO&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;systemConfigApi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;systemConfigDTO&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrating Tools into Chatbot Service
&lt;/h3&gt;

&lt;p&gt;The chatbot service will handle the natural language processing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ITool&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;executeAIAndReturnString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;conversationId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;PromptTemplate&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;relevantHistory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conversationId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;formatMessage&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;joining&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

    &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"context"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;relevantHistory&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;chatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conversationId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toArray&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;chatMemory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conversationId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AssistantMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created an interface &lt;strong&gt;ITool&lt;/strong&gt; to unify all the tool functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;conversationId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;PromptTemplate&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptTemplate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AiPromptTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;QA_QUESTION_CLARIFY_TEMPLATE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"question"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chatModel&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;call&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;equals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptTemplate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AiPromptTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;QA_PROMPT_TEMPLATE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"question"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"language"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;LanguageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLanguage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

        &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptTemplate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;QA_TOOL_CALL_TEMPLATE&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"question"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"language"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;LanguageContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLanguage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;executeAIAndReturnString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conversationId&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"chat"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Attention: The chatbot has two functions: first, it serves as a Q&amp;amp;A chatbot; second, it acts as a configuration management chatbot. Therefore, there is a judgment to determine whether the question is a Q&amp;amp;A query or a configuration management query before calling the LLM&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Interactions
&lt;/h2&gt;

&lt;p&gt;Here are some example interactions with the chatbot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3j6bo7auzyjnkfagej5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3j6bo7auzyjnkfagej5.jpg" alt="Image description" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, I input "Query System Configurations" then the chatbot will return the current system configuration settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl91vjmmsj7fzvqyyvaea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl91vjmmsj7fzvqyyvaea.png" alt="Image description" width="800" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I input 'Get value of Auto Release Delay Time,' and the chatbot returns the current value. Then, I input 'Set value to 10 min' to update it. The chatbot confirms the change by returning the new value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;p&gt;When implementing this type of system, consider these security aspects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Authentication and Authorization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure only authorized users can access the configuration chatbot&lt;/li&gt;
&lt;li&gt;Implement role-based access control for different configuration categories&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Validation and Constraints&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add validation rules for configuration values&lt;/li&gt;
&lt;li&gt;Implement constraints to prevent critical system settings from being modified&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Audit Logging&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log all configuration changes&lt;/li&gt;
&lt;li&gt;Record who made the change and when&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Benefits and Use Cases
&lt;/h2&gt;

&lt;p&gt;This approach to configuration management offers several advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Improved User Experience&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Natural language interaction reduces the learning curve&lt;/li&gt;
&lt;li&gt;Users don't need to remember exact configuration keys&lt;/li&gt;
&lt;li&gt;Faster configuration changes without navigating complex interfaces&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reduced Human Error&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The AI can validate and sanitize inputs&lt;/li&gt;
&lt;li&gt;Immediate feedback on invalid configurations&lt;/li&gt;
&lt;li&gt;Guided experience for complex settings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Perfect for DevOps and System Administration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quick configuration changes during deployments&lt;/li&gt;
&lt;li&gt;Easier troubleshooting and system maintenance&lt;/li&gt;
&lt;li&gt;Reduced documentation needs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Other Use Cases with function call
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Customer Support: Automatically create support tickets, fetch order details, or provide FAQs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E-commerce: Recommend products, process payments, or track shipments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Healthcare: Schedule appointments, retrieve patient records, or send medication reminders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Finance: Fetch account balances, perform transactions, or provide investment insights.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining Spring AI with system configuration management, we've created a more intuitive and user-friendly way to manage application settings. This approach shows how AI can simplify traditional technical tasks and make them accessible to a broader audience.&lt;/p&gt;

&lt;p&gt;The complete source code for this project is available on GitHub &lt;a href="https://github.com/jingsewu/open-wes" rel="noopener noreferrer"&gt;OpenWES&lt;/a&gt;. Feel free to try it out and adapt it to your needs!&lt;/p&gt;

&lt;p&gt;Remember to handle edge cases, add proper error handling, and implement security measures before using this in a production environment.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
      <category>springboot</category>
    </item>
  </channel>
</rss>
