Spring自定义HTTP请求注解

1、Http请求URL注解定义

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface HttpUrl {
    String prefixUrl();
}

2、Http请求发送注解定义

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface HttpRequest {
    HttpMethod method() default HttpMethod.POST;

    String value();
}

3、Http注解启动注解定义

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({HttpRequestRegistrar.class})
public @interface EnableHttpRequest {
    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] defaultConfiguration() default {};
}

4、解码器定义

public interface Decoder {
    Object decode(ResponseEntity responseEntity, Type type) throws Exception;
}
public class DistanceDecoder implements Decoder{

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     *数据解码
     * @param response
     * @param type
     * @return
     * @throws Exception
     */
    @Override
    public Object decode(ResponseEntity response, Type type) throws Exception {
        Object body = response.getBody();
        String value = null;
        if (body instanceof String) {
            value = (String)body;
        }

        JavaType javaType = this.getJavaType(type, null);
        return this.objectMapper.readValue(value, javaType);
    }

    protected JavaType getJavaType(Type type, Class<?> contextClass) {
        return contextClass != null ? this.objectMapper.getTypeFactory().constructType(type, contextClass) : this.objectMapper.constructType(type);
    }
}

5、请求代理处理器

@Slf4j
public class DistanceHandler implements EnvironmentAware {

    @Autowired(required = true)
    private HttpRequestHandler httpRequestHandler;

    private Environment environment;

    public Object handle(Object proxy,Method method, Object[] args) {
        RestTemplate restTemplate = RestTemplateSingleton.getInstance();
        HttpRequest request = method.getAnnotation(HttpRequest.class);
        String value = request.value();
        HttpMethod httpMethod = request.method();
        Type returnType = method.getGenericReturnType();
        Class<?> declaringClass = method.getDeclaringClass();
        Annotation[][] annotations = method.getParameterAnnotations();
        HttpUrl httpConnection = declaringClass.getAnnotation(HttpUrl.class);
        String prefixUrl = httpConnection.prefixUrl();
        //解析占位符
        prefixUrl = this.resolve(prefixUrl);
        String requestUrl = prefixUrl + (prefixUrl.endsWith("/") ? "" : "/") + value;
        String name = httpMethod.name();
        if ("POST".equals(name)) {
            return this.httpRequestHandler.doPost(restTemplate, annotations, args, httpMethod, requestUrl, returnType,method);
        } else {
            return "GET".equals(name) ? this.httpRequestHandler.doGet(restTemplate, annotations, args, httpMethod, requestUrl, returnType,method) : null;
        }
    }

    public HttpRequestHandler getHttpRequestHandler() {
        return this.httpRequestHandler;
    }

    public void setHttpRequestHandler(HttpRequestHandler httpRequestHandler) {
        this.httpRequestHandler = httpRequestHandler;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    /**
     * 占位符解析
     */
    private String resolve(String value) {
        if (StringUtils.hasText(value)) {
            return this.environment.resolvePlaceholders(value);
        }
        return value;
    }
}

6、请求处理器

@Slf4j
public class HttpRequestHandler {

    @Autowired
    private Decoder decoder;

    private static final String HTTP_FORM = "application/x-www-form-urlencoded";

    private static final String HTTP_JSON = "application/json; charset=UTF-8";

    /**
     * post请求
     * @param restTemplate
     * @param headers
     * @param annotations
     * @param args
     * @param httpMethod
     * @param requestUrl
     * @param type
     * @return
     */
    public Object doPost(RestTemplate restTemplate, Annotation[][] annotations, Object[] args, HttpMethod httpMethod, String requestUrl, Type type, Method method) {
        HttpHeaders headers = getHeader(args);
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap();
        RequestParam requestParam = null;
        HttpEntity httpEntity = null;
        String jsonStr = null;
        MediaType mediaType = null;
        String httpFamat = null;

        if(ArrayUtils.isNotEmpty(annotations)){
            for(int i = 0; i < annotations.length; i++) {
                Annotation[] parmAnnotations = annotations[i];
                if(ArrayUtils.isNotEmpty(parmAnnotations)){
                    for (int j = 0;j < parmAnnotations.length;j++){
                        if (parmAnnotations[j] instanceof RequestBody) {
                            httpFamat = HTTP_JSON;
                            break;
                        }
                    }
                }
            }
        }

        if(StringUtils.isEmpty(httpFamat)){
            httpFamat = HTTP_FORM;
            mediaType = MediaType.parseMediaType(httpFamat);
            headers.setContentType(mediaType);
            Map<String,Object> map = null;

            if(hasHeader(args)){
                if(args[1] instanceof Map){
                    map = (Map) args[1];
                }
            }else {
                if(args[0] instanceof Map){
                    map = (Map) args[1];
                }
            }

            if(MapUtils.isEmpty(map)){
                if(ArrayUtils.isNotEmpty(annotations)){
                    for(int i = 0; i < annotations.length; i++) {
                        Annotation[] parmAnnotations = annotations[i];
                        if(ArrayUtils.isNotEmpty(parmAnnotations)){
                            for (int j = 0;j < parmAnnotations.length;j++){
                                if (parmAnnotations[j] instanceof RequestParam) {
                                    requestParam = (RequestParam)parmAnnotations[j];
                                    jsonStr = requestParam.value();
                                    paramMap.add(jsonStr, args[i]);
                                    break;
                                }else {
                                    if(hasHeader(args) && i != 0){
                                        paramMap.add(method.getParameters()[i].getName(), args[i]);
                                    }
                                    break;
                                }
                            }
                        }else {
                            if(hasHeader(args) && i != 0){
                                paramMap.add(method.getParameters()[i].getName(), args[i]);
                            }
                        }
                    }
                }else {
                    for (int i = 0;i < args.length;i++){
                        paramMap.add(method.getParameters()[i].getName(),args[i]);
                    }
                }
            }else {
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    String key = entry.getKey();
                    Object value = entry.getValue();
                    paramMap.add(key,value);
                }
            }


            httpEntity = new HttpEntity(paramMap, headers);
        }else {
            jsonStr = JSONObject.toJSONString(args[0]);
            httpFamat = HTTP_JSON;
            mediaType = MediaType.parseMediaType(httpFamat);
            headers.setContentType(mediaType);
            headers.add("Accept", MediaType.APPLICATION_JSON.toString());
            httpEntity = new HttpEntity(jsonStr, headers);
        }

        log.info("发起HTTP请求,请求URL为:{},请求格式:{},请求方式:{},请求参数:{}",requestUrl,httpFamat,httpMethod.name(), JSON.toJSONString(args));

        ResponseEntity<String> responseEntity = null;
        ParameterizedTypeReference parameterizedTypeReference = new ParameterizedTypeReference<String>() {
        };
        responseEntity = restTemplate.exchange(requestUrl, httpMethod, httpEntity, parameterizedTypeReference);
        Object decode = null;

        try {
            decode = this.decoder.decode(responseEntity, type);
        } catch (Exception e) {
            HttpRequestHandler.log.error("http解码异常{}", e);
        }

        log.info("HTTP请求响应数据为:{}", JSON.toJSONString(decode));
        return decode;
    }

    public Object doGet(RestTemplate restTemplate, Annotation[][] annotations, Object[] args, HttpMethod httpMethod, String requestUrl, Type type,Method method) {
        HttpHeaders headers = getHeader(args);
        requestUrl = requestUrl + "?";
        Map<String, Object> paramMap = new HashMap();
        RequestParam requestParam = null;

        ResponseEntity responseEntity = null;

        String paramValue = null;

        if(ArrayUtils.isNotEmpty(annotations)){
            for(int i = 0; i < annotations.length; i++) {
                Annotation[] parmAnnotations = annotations[i];
                if(ArrayUtils.isNotEmpty(parmAnnotations)){
                    for (int j = 0;j < parmAnnotations.length;j++){
                        if (parmAnnotations[j] instanceof RequestParam) {
                            requestParam = (RequestParam)parmAnnotations[j];
                            paramMap.put(requestParam.value(), args[i]);
                            break;
                        }else {
                            if(hasHeader(args) && i != 0){
                                paramMap.put(method.getParameters()[i].getName(), args[i]);
                            }
                            break;
                        }
                    }
                }else {
                    if(hasHeader(args) && i != 0){
                        paramMap.put(method.getParameters()[i].getName(), args[i]);
                    }
                }
            }
        }else {
            for (int i = 0;i < args.length;i++){
                paramMap.put(method.getParameters()[i].getName(),args[i]);
            }
        }

        for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            requestUrl += key + "={" + value + "}&";
        }

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity(null, headers);
        ParameterizedTypeReference parameterizedTypeReference = new ParameterizedTypeReference<String>() {
        };

        //请求数据
        responseEntity = restTemplate.exchange(requestUrl, httpMethod, httpEntity, parameterizedTypeReference, paramMap);
        Object decode = null;

        try {
            decode = this.decoder.decode(responseEntity, type);
        } catch (Exception e) {
            HttpRequestHandler.log.error("http解码异常{}", e);
        }

        return decode;
    }

    private HttpHeaders getHeader(Object[] args){
        final HttpHeaders[] headers = {null};
        //判断参数是否有请求头信息
        Arrays.stream(args).forEach(
                arg -> {
                    if(arg instanceof HttpHeaders){
                        headers[0] = (HttpHeaders) arg;
                        return;
                    }
                }
        );
        if(headers[0] == null){
            headers[0] = new HttpHeaders();
        }

        return headers[0];
    }

    private boolean hasHeader(Object[] args){
        final boolean[] flag = {false};
        Arrays.stream(args).forEach(
                arg -> {
                    if(arg instanceof HttpHeaders){
                        flag[0] = true;
                        return;
                    }
                }
        );

        return flag[0];
    }
}

7、核心注册类

@Slf4j
public class HttpRequestRegistrar implements ImportBeanDefinitionRegistrar,ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware, BeanFactoryAware {

    private static final String SCAN_BASE_PACKAGE_DEFAULT = "com.wjhd";

    private String[] scanBasePackages;

    private ClassLoader classLoader;

    private ResourceLoader resourceLoader;

    private Environment environment;

    private BeanFactory beanFactory;

    //注册相关处理类
    private void registerDefaultConfiguration(AnnotationMetadata metadata,
                                              BeanDefinitionRegistry registry) {
        Map<String, Object> defaultAttrs = metadata
                .getAnnotationAttributes(EnableHttpRequest.class.getName(), true);

        //获取包的扫描路径
        String[] value = (String[]) defaultAttrs.get("value");
        if(ArrayUtils.isNotEmpty(value)){
            this.scanBasePackages = value;
        }else {
            String[] basePackages = (String[]) defaultAttrs.get("basePackages");
            if(ArrayUtils.isNotEmpty(basePackages)){
                this.scanBasePackages = basePackages;
            }
        }

        if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
            BeanDefinitionBuilder builderDistanceDecoder = BeanDefinitionBuilder
                    .genericBeanDefinition(DistanceDecoder.class);
            registry.registerBeanDefinition("distanceDecoder",builderDistanceDecoder.getBeanDefinition());

            BeanDefinitionBuilder builderDistanceHandler = BeanDefinitionBuilder
                    .genericBeanDefinition(DistanceHandler.class);
            builderDistanceHandler.setLazyInit(false);
            registry.registerBeanDefinition("builderDistanceHandler",builderDistanceHandler.getBeanDefinition());

            BeanDefinitionBuilder builderHttpRequestHandler = BeanDefinitionBuilder
                    .genericBeanDefinition(HttpRequestHandler.class);
            builderHttpRequestHandler.setLazyInit(false);
            registry.registerBeanDefinition("builderHttpRequestHandler",builderHttpRequestHandler.getBeanDefinition());
        }

        registerProxy(registry);
    }

    private void registerProxy(BeanDefinitionRegistry beanDefinitionRegistry){
        try {
            ClassPathScanningCandidateComponentProvider classScanner = this.getClassScanner();
            classScanner.setResourceLoader(this.resourceLoader);
            AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(HttpUrl.class);
            classScanner.addIncludeFilter(annotationTypeFilter);

            log.info("开始扫描http请求bean。。。。。");
            //扫描Bean
            for (String basePackage : getScanBasePackages()) {
                //注册bean
                Set<BeanDefinition> beanDefinitionSet = classScanner.findCandidateComponents(basePackage);
                Iterator iterator = beanDefinitionSet.iterator();
                while(iterator.hasNext()) {
                    BeanDefinition beanDefinition = (BeanDefinition)iterator.next();
                    if (beanDefinition instanceof AnnotatedBeanDefinition) {
                        this.registerBeans((AnnotatedBeanDefinition)beanDefinition);
                    }
                }
            }

        } catch (Exception e) {
            log.error("distance初始化异常" + e);
        }
    }

    private void registerBeans(AnnotatedBeanDefinition annotatedBeanDefinition) {
        String className = annotatedBeanDefinition.getBeanClassName();
        ((DefaultListableBeanFactory)this.beanFactory).registerSingleton(className, this.createProxy(annotatedBeanDefinition));
    }

    private Object createProxy(AnnotatedBeanDefinition annotatedBeanDefinition) {
        try {
            AnnotationMetadata annotationMetadata = annotatedBeanDefinition.getMetadata();
            Class<?> target = Class.forName(annotationMetadata.getClassName());
            InvocationHandler invocationHandler = this.createInvocationHandler();
            Object proxy = Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target}, invocationHandler);
            return proxy;
        } catch (ClassNotFoundException e) {
            HttpRequestRegistrar.log.error(e.getMessage());
            return null;
        }
    }

    private InvocationHandler createInvocationHandler() {
        return new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                DistanceHandler distanceHandler = HttpRequestRegistrar.this.beanFactory.getBean(DistanceHandler.class);
                HttpRequestHandler httpRequestHandler = distanceHandler.getHttpRequestHandler();
                if (httpRequestHandler == null) {
                    distanceHandler.setHttpRequestHandler(HttpRequestRegistrar.this.beanFactory.getBean(HttpRequestHandler.class));
                }
                return distanceHandler.handle(proxy, method, args);
            }
        };
    }

    private ClassPathScanningCandidateComponentProvider getClassScanner() {
        return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
            protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
                if (beanDefinition.getMetadata().isInterface()) {
                    try {
                        Class<?> target = ClassUtils.forName(beanDefinition.getMetadata().getClassName(), HttpRequestRegistrar.this.classLoader);
                        return !target.isAnnotation();
                    } catch (Exception var3) {
                        HttpRequestRegistrar.log.error("loadClass Exception:", var3);
                    }
                }

                return false;
            }
        };
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    public String[] getScanBasePackages() {
        if (scanBasePackages == null || scanBasePackages.length == 0) {
            return new String[]{SCAN_BASE_PACKAGE_DEFAULT};
        }
        return scanBasePackages;
    }

    public void setScanBasePackages(String[] scanBasePackages) {
        this.scanBasePackages = scanBasePackages;
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        this.registerDefaultConfiguration(annotationMetadata,beanDefinitionRegistry);
    }
}

8、RestTemplate请求类

public class RestTemplateSingleton {
    static volatile RestTemplate restTemplate;

    public RestTemplateSingleton() {
    }

    public static RestTemplate getInstance() {
        if (restTemplate == null) {
            Class var0 = RestTemplateSingleton.class;
            synchronized(RestTemplateSingleton.class) {
                if (restTemplate == null) {
                    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
                    requestFactory.setConnectTimeout(300000);
                    requestFactory.setReadTimeout(300000);
                    restTemplate = new RestTemplate(requestFactory);
                }
            }
        }

        return restTemplate;
    }
}

9、启动类开启注解

@SpringBootApplication
@EnableHttpRequest("com.lpforum.lpforumweb.core.netease")
public class LpforumApplication {

    public static void main(String[] args) {
        SpringApplication.run(LpforumApplication .class, args);
    }

}

10、调用云信第三方接口测试

    @HttpRequest(value = "/user/getUinfos.action",method = HttpMethod.GET)
    TokenRet createNetEaseAcc(HttpHeaders headers, Map params) throws Exception;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Spring Boot整合Spring Security自定义登录的步骤: 1. 引入依赖:在pom.xml文件中引入Spring Security和Thymeleaf的依赖。 2. 配置Spring Security:在Spring Boot的配置类中添加@EnableWebSecurity注解,并继承WebSecurityConfigurerAdapter类,重写configure(HttpSecurity http)方法,配置登录页面、登录请求、登录成功后的跳转等信息。 3. 自定义登录页面:在resources/templates目录下创建login.html文件,使用Thymeleaf模板引擎实现自定义登录页面。 4. 自定义登录表单:在login.html文件中添加表单,表单中包含用户名和密码两个输入框。 5. 自定义登录请求:在Spring Boot的控制器类中添加/login请求的处理方法,该方法接收用户名和密码参数,并使用Spring Security提供的AuthenticationManager进行认证。 6. 自定义认证逻辑:在Spring Security的配置类中重写configure(AuthenticationManagerBuilder auth)方法,实现自定义的认证逻辑。 7. 自定义登录成功后的跳转:在Spring Security的配置类中重写configure(HttpSecurity http)方法,配置登录成功后的跳转页面。 下面是示例代码: 1. 引入依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> ``` 2. 配置Spring Security: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/login", "/register").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/home") .permitAll() .and() .logout() .permitAll(); } } ``` 3. 自定义登录页面: ```html <!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Login</title> </head> <body> <h1>Login</h1> <form th:action="@{/login}" method="post"> <div> <label for="username">Username:</label> <input type="text" id="username" name="username" required autofocus> </div> <div> <label for="password">Password:</label> <input type="password" id="password" name="password" required> </div> <button type="submit">Login</button> </form> </body> </html> ``` 4. 自定义登录表单:在login.html文件中添加表单,表单中包含用户名和密码两个输入框。 5. 自定义登录请求: ```java @Controller public class LoginController { @GetMapping("/login") public String login() { return "login"; } @PostMapping("/login") public String doLogin(@RequestParam String username, @RequestParam String password) { // 使用AuthenticationManager进行认证 return "redirect:/home"; } } ``` 6. 自定义认证逻辑: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); } } ``` 7. 自定义登录成功后的跳转: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/login", "/register").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/home") .permitAll() .and() .logout() .permitAll(); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值