1.定义处理器接口
public interface SmsHandler {
/**
* 登录
/
String LOGIN_CODE = “1000”;
/*
* 注册
/
String REGISTER_CODE = “1001”;
/*
* 重置密码
/
String RESET_PWD_CODE = “1002”;
/*
* 创建订单
/
String CREATE_ORDER_CODE = “1003”;
/*
* 修改手机号
*/
String RESET_PHONE_CODE = “1004”;
void handle(String phoneNumber);
}
2.自定义注解@HandlerType,用于标识该处理器对应哪个业务类型
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HandlerType {
String value();
}
3.根据不同业务场景,定义处理器
场景1:
@Component
@HandlerType(SmsHandler.LOGIN_CODE)
public class LoginSmsHandler implements SmsHandler {
private static Logger logger = LoggerFactory.getLogger(LoginSmsHandler.class);
/**
* 用户登录,获取短信验证码
*/
@Override
public void handle(String phoneNumber) {
logger.info(“即将发送用户登录短信验证码 phoneNumber = {}”, phoneNumber);
}
}
场景2:
@Component
@HandlerType(SmsHandler.REGISTER_CODE)
public class RegisterSmsHandler implements SmsHandler {
private static Logger logger = LoggerFactory.getLogger(RegisterSmsHandler.class);
@Autowired
private UserService userService;
/**
* 修改密码 获取短信验证码
*/
@Override
public void handle(String phoneNumber) {
//用户已经注册,抛出自定义异常 BizException
SysUser model = userService.findUserByPhoneNumber(phoneNumber);
if (model != null) {
throw new BizException(UserErrorCode.ERROR_1017);
}
logger.info(“新用户注册,即将发送短信验证码 phoneNumber = {}”, phoneNumber);
}
}
4.定义HandlerContext上下文,用来保存不同的业务处理器
public class HandlerContext {
private Map<String, Class<?>> handlerMap;
public HandlerContext(Map<String, Class<?>> handlerMap) {
super();
this.handlerMap = handlerMap;
}
public SmsHandler getInstance(String type) {
Class<?> clazz = handlerMap.get(type);
if (clazz == null) {
throw new BizException(ErrorCode.SYS_9001,“短信验证码类型错误”);
}
Object bean = ApplicationContext.getBean(clazz);
return (SmsHandler) bean;
}
}
ApplicationContext 工具类源码:
@Component
public class ApplicationContext implements ApplicationContextAware {
private static org.springframework.context.ApplicationContext context;
public static T getBean(String beanName) {
return (T) ApplicationContext.context.getBean(beanName);
}
public static T getBean(Class clazz) {
return (T) ApplicationContext.context.getBean(clazz);
}
@Override
public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext)
throws BeansException {
ApplicationContext.context = applicationContext;
}
}
5.初始化HandlerContext,将其注册到spring容器中
@Component
@SuppressWarnings({ “unchecked” })
public class HandlerProcessor implements BeanFactoryPostProcessor {
private static final String HANDLER_PACKAGE = “com.admat.user.handler”;
/**
* 扫描@HandlerType,初始化HandlerContext,将其注册到spring容器
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
HashMap<String, Class<?>> handlerMap = Maps.newHashMapWithExpectedSize(16);
Map<Class<? extends Annotation>, Collection< Class<?>>> scan = null;
try {
scan = ClassScanner.scan(HANDLER_PACKAGE, HandlerType.class);
Set<Class<? extends Annotation>> keySet = scan.keySet();
for (Class<? extends Annotation> key : keySet) {
Collection<Class<?>> collection = scan.get(key);
for (Class<?> clazz : collection) {
String type = clazz.getAnnotation(HandlerType.class).value();
handlerMap.put(type, clazz);
}
}
HandlerContext context = new HandlerContext(handlerMap);
beanFactory.registerSingleton(HandlerContext.class.getName(), context);
} catch (Exception e) {
throw new RuntimeException(“初始化HandlerContext失败”, e);
}
}
}
6.调用
@RequestMapping("/phone")
@Controller
public class PhoneCodeController{
private static Logger logger = LoggerFactory.getLogger(PhoneCodeController.class);
@Autowired
private HandlerContext handlerContext;
/**
* 手机验证码
*/
@ResponseBody
@RequestMapping(value = “/phoneCode”)
public String phoneCode(String phoneNumber, String type) throws Exception {
// 校验是否发送短信验证码
SmsHandler handler = handlerContext.getInstance(type);
handler.handle(phoneNumber);
String code = RandomUtils.randomPhoneCode(6);
//TODO 业务逻辑
return null;
}
}
ClassScanner:工具类源码:
public class ClassScanner {
private static final String ALL_FILES = “**/";
private static final String ALL_CLASS_FILES = ALL_FILES + “.class”;
private static final String WILDCARD = "”;
@SuppressWarnings(“unchecked”)
public static Map<Class<? extends Annotation>, Collection< Class<?>>> scan(String basePackage,
Class<? extends Annotation>… annotations) throws IOException, ClassNotFoundException {
return findClasses(parsePackages(basePackage), Collections.unmodifiableList(Arrays.asList(annotations)), null);
}
private static Set parsePackages(final String packagesAsCsv) {
final String[] values = StringUtils.split(packagesAsCsv, “,”);
final Set basePackages = new HashSet(values.length);
for (final String value : values) {
final String trimmed = value.trim();
if (trimmed.equals(WILDCARD)) {
basePackages.clear();
basePackages.add(trimmed);
break;
} else if (trimmed.length() > 0) {
basePackages.add(trimmed);
}
}
return basePackages;
}
private static Map<Class<? extends Annotation>, Collection< Class<?>>> findClasses(Collection basePackages,
List<Class<? extends Annotation>> annotations, ClassLoader loader)
throws IOException, ClassNotFoundException {
ResourcePatternResolver resolver = getResolver(loader);
MetadataReaderFactory factory = new CachingMetadataReaderFactory(resolver);
final Map<Class<? extends Annotation>, Collection< Class<?>>> classes = new HashMap<Class<? extends Annotation>, Collection< Class<?>>>();
final Map<Class<? extends Annotation>, Collection> matchingInterfaces = new HashMap<Class<? extends Annotation>, Collection>();
final Map<String, String[]> nonMatchingClasses = new HashMap<String, String[]>();
for (Class<? extends Annotation> annotation : annotations) {
classes.put(annotation, new HashSet<Class<?>>());
matchingInterfaces.put(annotation, new HashSet());
}
if (basePackages == null || basePackages.isEmpty()) {
return classes;
}
for (final String basePackage : basePackages) {
final boolean scanAllPackages = basePackage.equals(WILDCARD);
final String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ (scanAllPackages ? “” : ClassUtils.convertClassNameToResourcePath(basePackage)) + ALL_CLASS_FILES;
final Resource[] resources = resolver.getResources(packageSearchPath);
for (final Resource resource : resources) {
final MetadataReader reader = factory.getMetadataReader(resource);
final AnnotationMetadata metadata = reader.getAnnotationMetadata();
for (Class<? extends Annotation> annotation : annotations) {
boolean concreteClass = !metadata.isInterface() && !metadata.isAbstract();
if (metadata.isAnnotated(annotation.getName())) {
if (concreteClass) {
classes.get(annotation).add(loadClass(metadata.getClassName(), loader));
} else {
matchingInterfaces.get(annotation).add(metadata.getClassName());
}
} else if (concreteClass && metadata.getInterfaceNames().length > 0) {
nonMatchingClasses.put(metadata.getClassName(), metadata.getInterfaceNames());
}
}
}
}
if (!nonMatchingClasses.isEmpty()) {
for (Map.Entry<Class<? extends Annotation>, Collection> e1 : matchingInterfaces.entrySet()) {
for (Map.Entry<String, String[]> e2 : nonMatchingClasses.entrySet()) {
for (String intName : e2.getValue()) {
if (e1.getValue().contains(intName)) {
classes.get(e1.getKey()).add(loadClass(e2.getKey(), loader));
break;
}
}
}
}
}
for (Map.Entry<Class<? extends Annotation>, Collection> e : matchingInterfaces.entrySet()) {
if (classes.get(e.getKey()).isEmpty()) {
for (String intName : e.getValue()) {
classes.get(e.getKey()).add(loadClass(intName, loader));
}
}
}
return classes;
}
private static ResourcePatternResolver getResolver(ClassLoader loader) {
return loader != null ? new PathMatchingResourcePatternResolver(loader)
: new PathMatchingResourcePatternResolver();
}
private static Class<?> loadClass(String className, ClassLoader loader) throws ClassNotFoundException {
if (loader == null) {
try {
ClassLoader cl = getContextClassLoader();
if (cl != null) {
return cl.loadClass(className);
}
} catch (ClassNotFoundException e) {
}
return loadClass2(className, ClassScanner.class);
} else {
return loader.loadClass(className);
}
}
private static ClassLoader getContextClassLoader() {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction() {
public ClassLoader run() {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
return loader != null ? loader : ClassLoader.getSystemClassLoader();
}
});
}
ClassLoader loader = Thread.currentThread().getContextClassLoader();
return loader != null ? loader : ClassLoader.getSystemClassLoader();
}
private static Class<?> loadClass2(String className, Class<?> callingClass) throws ClassNotFoundException {
try {
return Class.forName(className);
} catch (ClassNotFoundException ex) {
final ClassLoader loader = getClassLoader(callingClass);
if (loader != null) {
return loader.loadClass(className);
} else {
throw ex;
}
}
}
private static ClassLoader getClassLoader(final Class<?> clazz) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
return AccessController.doPrivileged(new PrivilegedAction() {
public ClassLoader run() {
return clazz.getClassLoader();
}
});
}
return clazz.getClassLoader();
}
}