精华内容
下载资源
问答
  • 如何使用自定义注解

    千次阅读 2015-03-15 16:16:47
    Java注解目前广泛被应用。spring中的基于注解的依赖注入、Spring Web MVC中的Route、PlayFramework中的...现在来看看,如何自定义注解。 目标:通过注解方式,定义属性的默认值。例如: [java] view plaincopy

    Java注解目前广泛被应用。spring中的基于注解的依赖注入、Spring Web MVC中的Route、PlayFramework中的基于注解的Validation等。

    使用注解,可以在适当地方替代XML的繁琐。


    现在来看看,如何自定义注解。

    目标:通过注解方式,定义属性的默认值。例如:

    [java] view plaincopy
    1. public class DefaultUse {  
    2.       
    3.     @Default(value = "Hello Annotation")  
    4.     private String msg;  
    5.       
    6.     public void say(){  
    7.         System.out.println(msg);  
    8.     }  
    9. }  


    一、新建Annotation

    [java] view plaincopy
    1. import java.lang.annotation.ElementType;  
    2. import java.lang.annotation.Retention;  
    3. import java.lang.annotation.RetentionPolicy;  
    4. import java.lang.annotation.Target;  
    5.   
    6. /** 
    7.  * @Retention 指定注释的生存时期 
    8.  * CLASS:注释记录在类文件中,但在运行时 VM 不需要保留注释。 
    9.  * RUNTIME:注释记录在类文件中,在运行时 VM 将保留注释,因此可以使用反射机制读取注释内容。 
    10.  * SOURCE:编译器要丢弃的注释。 
    11.  */  
    12. @Retention(RetentionPolicy.RUNTIME)   
    13.   
    14. /** 
    15.  * @Target  
    16.  * 指示注释类型所适用的程序元素的种类,如果注释类型声明中不存在 Target 元注释, 
    17.  * 则声明的类型可以用在任一程序元素上。 
    18.  * ElementType.ANNOTATION_TYPE:注释类型声明 
    19.  * ElementType.CONSTRUCTOR:构造方法声明 
    20.  * ElementType.FILED:字段声明 
    21.  * ElementType.LOCAL_VARIABLE:局部变量声明 
    22.  * ElementType.METHOD:方法声明 
    23.  * ElementType.PACKAGE:包声明 
    24.  * ElementType.PARAMETER:参数声明 
    25.  * ElementType.TYPE:类、借口或枚举声明 
    26.  */  
    27. @Target(ElementType.FIELD)  
    28. public @interface Default {  
    29.     String value(); //默认值  
    30. }  

    二、实际类中使用

    [java] view plaincopy
    1. public class DefaultUse {  
    2.       
    3.     @Default(value = "Hello Annotation")  
    4.     private String msg;  
    5.       
    6.     public void setMsg(String msg) {  
    7.         this.msg = msg;  
    8.     }  
    9.   
    10.     public void say(){  
    11.         System.out.println(msg);  
    12.     }  
    13. }  

    三、注解解析过程

    [java] view plaincopy
    1. import java.beans.PropertyDescriptor;  
    2. import java.lang.reflect.Field;  
    3. import java.lang.reflect.Method;  
    4.   
    5. public class DefaultTest {  
    6.     public static void main(String args[]) throws Exception{  
    7.         DefaultUse use = new DefaultUse();  
    8.           
    9.         //Default注解的处理过程  
    10.         //这里使用反射机制完成默认值的设置  
    11.         Field[] fileds = use.getClass().getDeclaredFields();  
    12.           
    13.         for(Field filed : fileds){  
    14.             Default annotation = filed.getAnnotation(Default.class);  
    15.             if(annotation != null){  
    16.                 PropertyDescriptor pd = new PropertyDescriptor(filed.getName(), DefaultUse.class);  
    17.                 Method setterName = pd.getWriteMethod();  
    18.                   
    19.                 if(setterName!=null){  
    20.                     String value = annotation.value();  
    21.                     filed.setAccessible(true);  
    22.                     setterName.invoke(use, value);  
    23.                 }  
    24.             }  
    25.         }  
    26.           
    27.         use.say();  
    28.     }  
    29. }  
    展开全文
  • 特别是开发Web应用时,我们会频繁的定义@Controller,@Service等JavaBean组件,通过注解,Spring自动扫描加载了这些组件,并提供相关的服务。Spring是如何读取注解信息,并注入到bean容器中的,本文就是通过嵌入...

    前言

    在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方法,了解一下Spring内部的处理逻辑。特别是开发Web应用时,我们会频繁的定义@Controller,@Service等JavaBean组件,通过注解,Spring自动扫描加载了这些组件,并提供相关的服务。

    Spring是如何读取注解信息,并注入到bean容器中的,本文就是通过嵌入Spring的Bean加载,来描述Spring的实现方法。完整的例子都在Github上了。

    自定义注解

    先看一个最简单的例子,在使用SpringWeb应用中的过程中,大家免不了会使用@Controller,@Service,@Repository等注解来定义JavaBean。那么怎么自己定义一个注解,Spring可以自动加载呢。所以就有了第一个例子。

    @Target({ ElementType.TYPE })

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    @Component

    public @interface MyComponent {

    String value() default

    "";

    }

    @Configuration

    public class ComponentAnnotationTest {

    public static void main(String[] args)

    {

    AnnotationConfigApplicationContext

    annotationConfigApplicationContext = new

    AnnotationConfigApplicationContext();

    annotationConfigApplicationContext.register(ComponentAnnotationTest.class);

    annotationConfigApplicationContext.refresh();

    InjectClass injectClass

    =

    annotationConfigApplicationContext.getBean(InjectClass.class);

    injectClass.print();

    }

    @MyComponent

    public static class InjectClass {

    public void print()

    {

    System.out.println("hello world");

    }

    }

    }

    运行这个例子,就会发现,@MyComponent

    注解的类,也被Spring加载进来了,而且可以当成普通的JavaBean正常的使用。查看Spring的源码会发现,Spring是使用ClassPathScanningCandidateComponentProvider扫描package,这个类有这样的注释

    A component provider that scans the classpath from a base

    package.

    It then applies exclude and include filters to the resulting

    classes to find candidates.

    这个类的 registerDefaultFilters 方法有这样几行代码

    protected void registerDefaultFilters() {

    this.includeFilters.add(new

    AnnotationTypeFilter(Component.class));

    ClassLoader cl =

    ClassPathScanningCandidateComponentProvider.class.getClassLoader();

    try {

    this.includeFilters.add(new AnnotationTypeFilter(((Class

    分享:

    a4c26d1e5885305701be709a3d33442f.png喜欢

    0

    a4c26d1e5885305701be709a3d33442f.png赠金笔

    加载中,请稍候......

    评论加载中,请稍候...

    发评论

    登录名: 密码: 找回密码 注册记住登录状态

    昵   称:

    评论并转载此博文

    a4c26d1e5885305701be709a3d33442f.png

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

    展开全文
  • 深入Spring:自定义注解加载和使用 前言 在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方法,了解一下Spring内部的处理逻辑。特别是开发Web应用时,我们会频繁的定义*@Controller*,*@Service*等...

    原文地址:http://www.cnblogs.com/wcongcode/p/5482239.html

    深入Spring:自定义注解加载和使用

    前言

    在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方法,了解一下Spring内部的处理逻辑。特别是开发Web应用时,我们会频繁的定义*@Controller**@Service*等JavaBean组件,通过注解,Spring自动扫描加载了这些组件,并提供相关的服务。
    Spring是如何读取注解信息,并注入到bean容器中的,本文就是通过嵌入Spring的Bean加载,来描述Spring的实现方法。完整的例子都在Github上了。

    自定义注解

    先看一个最简单的例子,在使用SpringWeb应用中的过程中,大家免不了会使用*@Controller**@Service**@Repository*等注解来定义JavaBean。那么怎么自己定义一个注解,Spring可以自动加载呢。所以就有了第一个例子。

    @Target({ ElementType.TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface MyComponent {
        String value() default "";
    }
    @Configuration
    public class ComponentAnnotationTest {
      public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
        annotationConfigApplicationContext.register(ComponentAnnotationTest.class);
        annotationConfigApplicationContext.refresh();
        InjectClass injectClass = annotationConfigApplicationContext.getBean(InjectClass.class);
        injectClass.print();
      }
      @MyComponent
      public static class InjectClass {
        public void print() {
            System.out.println("hello world");
        }
      }
    }

    运行这个例子,就会发现,*@MyComponent* 注解的类,也被Spring加载进来了,而且可以当成普通的JavaBean正常的使用。查看Spring的源码会发现,Spring是使用ClassPathScanningCandidateComponentProvider扫描package,这个类有这样的注释

    A component provider that scans the classpath from a base package. 
    It then applies exclude and include filters to the resulting classes to find candidates.

    这个类的 registerDefaultFilters 方法有这样几行代码

    protected void registerDefaultFilters() {   
       this.includeFilters.add(new AnnotationTypeFilter(Component.class));
       ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
       try {    
          this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>)     ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); 
          logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); 
       }   catch (ClassNotFoundException ex) {     
         // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.   
       }   
       try {      
          this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));      
          logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");   
       }  
       catch (ClassNotFoundException ex) {     
       // JSR-330 API not available - simply skip.  
       }
    }

    这里就会发现Spring在扫描类信息的使用只会判断被*@Component*注解的类所以任何自定义的注解只要带上*@Component*(当然还要有String value() default "";的方法,因为Spring的Bean都是有beanName唯一标示的),都可以被Spring扫描到,并注入容器内。

    定制功能

    但上面的方法太局限了,没办法定制,而且也没有实际的意义。如何用特殊的注解来实现定制的功能呢,一般有两种方式:

    1. 还是用上面的方法,在注入Spring的容器后,再取出来做自己定制的功能,Spring-MVC就是使用这样的方法。AbstractDetectingUrlHandlerMapping 中的 detectHandlers方法,这个方法取出了所有的bean,然后循环查找带有Controller的bean,并提取其中的RequestMapping信息

      protected void detectHandlers() throws BeansException {
          if (logger.isDebugEnabled()) {
              logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
          }
          String[] beanNames = (this.detectHandlersInAncestorContexts ?
                  BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                  getApplicationContext().getBeanNamesForType(Object.class));
      
          // Take any bean name that we can determine URLs for.
          for (String beanName : beanNames) {
              String[] urls = determineUrlsForHandler(beanName);
              if (!ObjectUtils.isEmpty(urls)) {
                  // URL paths found: Let's consider it a handler.
                  registerHandler(urls, beanName);
              }
              else {
                  if (logger.isDebugEnabled()) {
                      logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
                  }
              }
          }
      }
    2. 不依赖*@Component*,自定义扫描。所以就有了第二个例子。

    自定义扫描

    结构比较复杂,可以参考完整的例子,这里是关键的几个类

    1. 还是定义一个注解,只不过不再需要*@Component*了

      @Target({ ElementType.TYPE })
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      public @interface CustomizeComponent {
       String value() default "";
      }
    2. 注解修饰的类

      @CustomizeComponent
      public class ScanClass1 {
      public void print() {
          System.out.println("scanClass1");
      }
      }
    3. BeanScannerConfigurer用于嵌入到Spring的加载过程中,这里用到了BeanFactoryPostProcessor 和 ApplicationContextAware
      Spring提供了一些的接口使程序可以嵌入Spring的加载过程。这个类中的继承ApplicationContextAware接口,Spring会读取ApplicationContextAware类型的JavaBean,并调用setApplicationContext(ApplicationContext applicationContext)传入Spring的applicationContext
      同样继承BeanFactoryPostProcessor接口,Spring会在BeanFactory的相关处理完成后调用postProcessBeanFactory方法,进行定制的功能。

      @Component
      public static class BeanScannerConfigurer implements  BeanFactoryPostProcessor, ApplicationContextAware {
      private ApplicationContext applicationContext;
      
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
      }
      public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Scanner scanner = new Scanner((BeanDefinitionRegistry) beanFactory);
        scanner.setResourceLoader(this.applicationContext);
        scanner.scan("org.wcong.test.spring.scan");
      }
      }
    4. Scanner继承的ClassPathBeanDefinitionScanner是Spring内置的Bean定义的扫描器。
      includeFilter里定义了类的过滤器,newAnnotationTypeFilter(CustomizeComponent.class)表示只取被CustomizeComponent修饰的类。
      doScan里扫描了包底下的读取到的BeanDefinitionHolder,自定义GenericBeanDefinition相关功能。

      public final static class Scanner extends ClassPathBeanDefinitionScanner {
        public Scanner(BeanDefinitionRegistry registry) {
            super(registry);
        }
        public void registerDefaultFilters() {
            this.addIncludeFilter(new AnnotationTypeFilter(CustomizeComponent.class));
        }
        public Set<BeanDefinitionHolder> doScan(String... basePackages) {
            Set<BeanDefinitionHolder> beanDefinitions =   super.doScan(basePackages);
            for (BeanDefinitionHolder holder : beanDefinitions) {
                GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
                definition.getPropertyValues().add("innerClassName", definition.getBeanClassName());
                definition.setBeanClass(FactoryBeanTest.class);
            }
            return beanDefinitions;
        }
        public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
           return super.isCandidateComponent(beanDefinition) && beanDefinition.getMetadata()
      .hasAnnotation(CustomizeComponent.class.getName());
        }
      }
    5. FactoryBean是Spring中比较重要的一个类。它的描述如下

      Interface to be implemented by objects used within a BeanFactory which are themselves factories. 
      If a bean implements this interface, it is used as a factory for an object to expose, not directly as a bean* instance that will be exposed itself

      普通的JavaBean是直接使用类的实例,但是如果一个Bean继承了这个接口,就可以通过getObject()方法来自定义实例的内容,在FactoryBeanTest的getObject()就通过代理了原始类的方法,自定义类的方法。

      public static class FactoryBeanTest<T> implements InitializingBean, FactoryBean<T> {
        private String innerClassName;
        public void setInnerClassName(String innerClassName) {
            this.innerClassName = innerClassName;
        }
        public T getObject() throws Exception {
            Class innerClass = Class.forName(innerClassName);
            if (innerClass.isInterface()) {
                return (T) InterfaceProxy.newInstance(innerClass);
            } else {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(innerClass);
                enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
                enhancer.setCallback(new MethodInterceptorImpl());
                return (T) enhancer.create();
            }
        }
        public Class<?> getObjectType() {
            try {
                  return Class.forName(innerClassName);
            } catch (ClassNotFoundException e) {
                  e.printStackTrace();
            }
            return null;
        }
        public boolean isSingleton() {
            return true;
        }
        public void afterPropertiesSet() throws Exception {
        }
      }
      public static class InterfaceProxy implements InvocationHandler {
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("ObjectProxy execute:" + method.getName());
            return method.invoke(proxy, args);
        }
        public static <T> T newInstance(Class<T> innerInterface) {
            ClassLoader classLoader = innerInterface.getClassLoader();
            Class[] interfaces = new Class[] { innerInterface };
            InterfaceProxy proxy = new InterfaceProxy();
            return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
        }
       }
       public static class MethodInterceptorImpl implements MethodInterceptor {
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("MethodInterceptorImpl:" + method.getName());
            return methodProxy.invokeSuper(o, objects);
        }
      }
    6. main函数

      @Configuration
      public class CustomizeScanTest {
      public static void main(String[] args) {
          AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();                
          annotationConfigApplicationContext.register(CustomizeScanTest.class);
          annotationConfigApplicationContext.refresh();
          ScanClass1 injectClass = annotationConfigApplicationContext.getBean(ScanClass1.class);
          injectClass.print();
      }
      }

    至此一个完整的例子就完成了,这里主要用到了BeanFactoryPostProcessorApplicationContextAwareFactoryBean等Spring内置的接口,来嵌入Spring的加载和使用过程,这样就实现了自定义注解,和自定义代理了。

    展开全文
  • 一般来说,springboot提供的注解已经佷丰富了,但如果我们想针对某个特定情景来添加注解,就可以使用自定义注解。 自定义注解的步骤 实现这个自定义注解一般主要有以下几个步骤。 maven导入相关的依赖 声明注解 ...

    SPRINGBOOT自定义注解

    在springboot中,有各种各样的注解,这些注解能够简化我们的配置,提高开发效率。一般来说,springboot提供的注解已经佷丰富了,但如果我们想针对某个特定情景来添加注解,就可以使用自定义注解。

    自定义注解的步骤

    实现这个自定义注解一般主要有以下几个步骤。

    • maven导入相关的依赖
    • 声明注解
    • 注解的具体实现
    • 使用注解的实例

    在phyweb项目中的应用

    之所以会想到这个自定义注解,是因为我们在给用户发送邮件这个模块中,用户如果提交了请求,提交按钮被禁用,这个时候用户如果刷新页面的话,这仍然是一条post请求,而后面的这条请求我们不应该处理,而是提醒用户已经发送了。

    • 引入相关依赖
         <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
         </dependency>
    
         <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>21.0</version>
         </dependency>
    • 声明自定义注解
        @Target(ElementType.METHOD)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        @Inherited
        public @interface LocalLock {
            String key() default "";
            int expire() default 5;
        }
    
    • 注解实现
        @Aspect
        @Configuration
        public class LockMethodInterceptor {
        
            private static final Cache<String, Object> CACHES = CacheBuilder.newBuilder()
                    // 最大缓存 100 个
                    .maximumSize(1000)
                    // 设置写缓存后 60 秒钟过期
                    .expireAfterWrite(60, TimeUnit.SECONDS)
                    .build();
        
            @Around("execution(public * *(..)) && @annotation(com.buaabetatwo.phyweb.annotation.LocalLock)")
            public Object interceptor(ProceedingJoinPoint pjp) {
                myToken = 1;
                MethodSignature signature = (MethodSignature) pjp.getSignature();
                Method method = signature.getMethod();
                LocalLock localLock = method.getAnnotation(LocalLock.class);
                String key = getKey(localLock.key(), pjp.getArgs());
                if (!StringUtils.isEmpty(key)) {
                    if (CACHES.getIfPresent(key) != null) {
                        myToken = 0;
                        // throw new RuntimeException("请勿重复请求");
                    }
                    // 如果是第一次请求,就将 key 当前对象压入缓存中
                    CACHES.put(key, key);
                }
        
                try {
                    return pjp.proceed();
                } catch (Throwable throwable) {
                    throw new RuntimeException("服务器异常");
                } finally {
                    // CACHES.invalidate(key)
                }
            }
        
        
            private String getKey(String keyExpress, Object[] args) {
                for (int i = 0; i < args.length; i++) {
                    keyExpress = keyExpress.replace("arg[" + i + "]", args[i].toString());
                }
                return keyExpress;
            }
    • 使用注解
        @LocalLock(key = "myToken")  //
        @PostMapping("/reset-email")
        public String postResetEmail(String email, Model model) {
        }

    经过以上四个步骤,我们的自定义注解LocalLock就大功告成了,当用户打开密码找回页面,输入邮箱后,60秒内再次刷新页面会被拦截掉,也就是不会出现重复提交表单的情况了。如下图所示。

    1346565-20190518120045105-875078218.png

    转载于:https://www.cnblogs.com/mizhiniurou/p/10890951.html

    展开全文
  • 特别是开发Web应用时,我们会频繁的定义@Controller,@Service等JavaBean组件,通过注解,Spring自动扫描加载了这些组件,并提供相关的服务。 Spring是如何读取注解信息,并注入到bean容器中的,本文就是通过嵌入...
  • 深入Spring:自定义注解加载和使用 前言 在工作中经常使用Spring的相关框架,免不了去看一下Spring的实现方法,了解一下Spring内部的处理逻辑。特别是开发Web应用时,我们会频繁的定义@Controller,@Service等...
  • 序:对于注解的认知是从spring开始的,不管是aop还是ioc,对于其概念是比较清楚的,但真正的实现却没有一个比较好的认知,前段... 项目使用自定义注解和反射主要是为了在webSocket请求发过来的时候,通过请求中的参...
  • Java自定义注解

    千次阅读 2012-03-03 02:04:39
    Java注解目前广泛被应用。spring中的基于注解的依赖注入、Spring Web MVC中的Route、...现在来看看,如何自定义注解。 目标:通过注解方式,定义属性的默认值。例如: public class DefaultUse { @Default(value =
  • Spring自定义注解加载

    2018-11-16 15:57:13
    特别是开发Web应用时,我们会频繁的定义@Controller,@Service等JavaBean组件,通过注解,Spring自动扫描加载了这些组件,并提供相关的服务。 @Target({ ElementType.TYPE }) @Retention(RetentionPolicy.R...
  • SpringBoot集成JWT实现token验证(自定义注解) JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github.com/jwtk/jjwt 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种...
  • 1. 前言随着Spring的日渐臃肿,为了简化配置...平常我们用Spring Boot开发web应用。Spring mvc 默认使用tomcat servlet容器, 因为Spring mvc组件集成了spring-boot-starter-tomcat 。但是现在undertow servlet容器...
  • 特别是开发Web应用时,我们会频繁的定义@Controller,@Service等JavaBean组件,通过注解,Spring自动扫描加载了这些组件,并提供相关的服务。Spring是如何读取注解信息,并注入到bean容器中的,本文就是通过嵌入...
  • 1、要使用RequestMappingHandlerMapping组件 @RuquestMapping("/login.do"):该标记用在Controller业务方法前 2、Controller组件的编写和配置跟之前xml配置时不同,取消了实现Controller接口的约定,业务方法名也...
  • 上一节Springboot官网学习(7、Web应用程序【一 Spring Web MVC 之HttpMessageConverters消息转换器】)我们学习了自己定制消息转换器,SpringMVC框架使用HttpMessageConverter转换器类来转换http请求数据和响应数据...
  • 搭建项目时,通过引入SpringBoot为我提供的这些不同场景启动器,然后开发者再进行一些属性配置,便能够快速的开发出一个Java Web应用。究其原理,完全归结于SpringBoot封装的这些Starter为我们带来了众多的自动化...
  • 1.前言随着Spring的日渐臃肿,为了简化...平常我们用Spring Boot开发web应用。Spring mvc 默认使用tomcat servlet容器, 因为Spring mvc组件集成了spring-boot-starter-tomcat 。但是现在undertow servlet容器的性...
  • 前言:随着Spring的日渐臃肿,为了简化...平常我们用Spring Boot开发web应用。Spring mvc 默认使用tomcat servlet容器, 因为Spring mvc组件集成了spring-boot-starter-tomcat 。但是现在undertow servlet容器的性...
  • 在用Spring MVC框架做Web应用开发中,在一些特殊请款下我们都会用自定标签来完成一些特殊的功能。 在通常情况下,自定义标签的内容如果不通过访问服务就能实现,那么继承TagSupport,重写doStartTag()方法就可以...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 181
精华内容 72
关键字:

web应用使用自定义注解