1. 样板代码
1.1. 支付类型枚举
java
package com.example.demo.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 支付类型枚举
*
* @author wangbo
*/
@Getter
@AllArgsConstructor
public enum PaymentTypeEnum {
ALIPAY("alipay", "支付宝"),
WECHAT("wechat", "微信"),
UNIONPAY("unionpay", "银联");
private final String code;
private final String name;
}
1.2. 支付服务接口
java
package com.example.demo.service;
import com.example.demo.enums.PaymentTypeEnum;
import java.math.BigDecimal;
/**
* 支付服务
*
* @author wangbo
*/
public interface PaymentService {
/**
* 获取支付方式
*
* @return PaymentTypeEnum
*/
PaymentTypeEnum getPaymentType();
/**
* 处理支付
*
* @param amount 金额
*/
void processPayment(BigDecimal amount);
}
1.3. 支付服务实现类
java
package com.example.demo.service.impl;
import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 支付服务实现-支付宝支付
*
* @author wangbo
*/
@Slf4j
@Service
public class PaymentServiceAlipayImpl implements PaymentService {
@Override
public PaymentTypeEnum getPaymentType() {
return PaymentTypeEnum.ALIPAY;
}
@Override
public void processPayment(BigDecimal amount) {
log.info("支付宝支付: " + amount);
}
}
java
package com.example.demo.service.impl;
import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 支付服务实现-微信支付
*
* @author wangbo
*/
@Slf4j
@Service
public class PaymentServiceWechatImpl implements PaymentService {
@Override
public PaymentTypeEnum getPaymentType() {
return PaymentTypeEnum.WECHAT;
}
@Override
public void processPayment(BigDecimal amount) {
log.info("微信支付: " + amount);
}
}
1.4. 支付服务策略管理器
java
package com.example.demo.manager;
import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.PaymentService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 支付服务策略管理器
*
* @author wangbo
*/
@Component
@AllArgsConstructor
public class PaymentServiceStrategyManager {
private final List<PaymentService> paymentServices;
public PaymentService getPaymentService(PaymentTypeEnum paymentTypeEnum) {
for (PaymentService paymentService : paymentServices) {
if (paymentService.getPaymentType().equals(paymentTypeEnum)) {
return paymentService;
}
}
throw new IllegalArgumentException("不支持的支付方式: " + paymentTypeEnum.getName());
}
}
2. 使用代码
订单处理中需要调用支付服务
2.1. 订单服务接口
java
package com.example.demo.service;
import com.example.demo.enums.PaymentTypeEnum;
import java.math.BigDecimal;
/**
* 订单服务
*
* @author wangbo
*/
public interface OrderService {
/**
* 处理订单
*
* @param paymentTypeEnum 支付方式
* @param amount 支付金额
*/
void processOrder(PaymentTypeEnum paymentTypeEnum, BigDecimal amount);
}
2.2. 订单服务实现类
java
package com.example.demo.service.impl;
import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.manager.PaymentServiceStrategyManager;
import com.example.demo.service.OrderService;
import com.example.demo.service.PaymentService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 订单服务实现
*
* @author wangbo
*/
@Service
@AllArgsConstructor
public class OrderServiceImpl implements OrderService {
private final PaymentServiceStrategyManager paymentServiceStrategyManager;
@Override
public void processOrder(PaymentTypeEnum paymentTypeEnum, BigDecimal amount) {
PaymentService paymentService = paymentServiceStrategyManager.getPaymentService(paymentTypeEnum);
paymentService.processPayment(amount);
}
}
3. 测试代码
java
package com.example.demo.controller;
import com.example.demo.enums.PaymentTypeEnum;
import com.example.demo.service.OrderService;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
/**
* @author wangbo
* @since 2025/10/21
*/
@RestController
@AllArgsConstructor
public class OrderController {
private final OrderService orderService;
@GetMapping("/order")
public String processOrder() {
orderService.processOrder(PaymentTypeEnum.ALIPAY, BigDecimal.TEN);
return "支付成功";
}
@GetMapping("/order1")
public String processOrder1() {
orderService.processOrder(PaymentTypeEnum.WECHAT, BigDecimal.TEN);
return "支付成功";
}
@GetMapping("/order2")
public String processOrder2() {
orderService.processOrder(PaymentTypeEnum.UNIONPAY, BigDecimal.TEN);
return "支付成功";
}
}
http://localhost:8080/order
http://localhost:8080/order1
http://localhost:8080/order2
分别调用三次后,日志如下:
java
2025-10-21T12:01:11.144+08:00 INFO 32792 --- [demo] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2025-10-21T12:01:11.144+08:00 INFO 32792 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2025-10-21T12:01:11.146+08:00 INFO 32792 --- [demo] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2025-10-21T12:01:11.170+08:00 INFO 32792 --- [demo] [nio-8080-exec-1] c.e.d.s.impl.PaymentServiceAlipayImpl : 支付宝支付: 10
2025-10-21T12:01:21.053+08:00 INFO 32792 --- [demo] [nio-8080-exec-3] c.e.d.s.impl.PaymentServiceWechatImpl : 微信支付: 10
2025-10-21T12:01:26.791+08:00 ERROR 32792 --- [demo] [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalArgumentException: 不支持的支付方式: 银联] with root cause
java.lang.IllegalArgumentException: 不支持的支付方式: 银联
at com.example.demo.manager.PaymentServiceStrategyManager.getPaymentService(PaymentServiceStrategyManager.java:27) ~[main/:na]
at com.example.demo.service.impl.OrderServiceImpl.processOrder(OrderServiceImpl.java:24) ~[main/:na]
at com.example.demo.controller.OrderController.processOrder2(OrderController.java:35) ~[main/:na]
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) ~[spring-web-6.2.9.jar:6.2.9]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) ~[spring-web-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.2.9.jar:6.2.9]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.2.9.jar:6.2.9]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.43.jar:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.9.jar:6.2.9]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.43.jar:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.43.jar:10.1.43]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.2.9.jar:6.2.9]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.9.jar:6.2.9]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.2.9.jar:6.2.9]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.9.jar:6.2.9]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.2.9.jar:6.2.9]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.2.9.jar:6.2.9]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:398) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1769) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1189) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:658) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.43.jar:10.1.43]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]