• spring 源码解析


    1. [文件] spring源码.txt ~ 15B     下载(167)     

    1
    springн┤┬вио╬Ш:

    2. [文件] spring源码分析之AOP.txt ~ 15KB     下载(166)     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    spring源码解析
    spring----------
                    ---bean
                    ---aop
    1.什么是AOP
    OOP 面向对象编程
    AOP  面向切面,横切逻辑,用于在代码中插入公共片段
    SOA service-oriented architecture 面向服务架构
     AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
    * 传统方式,复用代码,继承, 扩展代码, 方法覆盖
    * 将复用代码抽取出来, 通过代理机制,将抽取代码 应用到目标对象
    * AOP 针对目标类 的方法进行 动态代理, 对原有方法 进行拦截增强
     
    1.1 AOP中的术语
    Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
    Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
    Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
    Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
    Target(目标对象):代理的目标对象
    Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.
        spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
    Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
    Aspect(切面): 是切入点和通知(引介)的结合
     
    1.2Spring AOP底层实现
      第一种 JDK 自带 动态代理技术
        * JDK 动态代理 必须 基于 接口 进行代理
        * 使用代理,对目标对象 进行性能监控(计算运行时间)、安全检查(是否具有权限)、 记录日志
    * 注意: 必须要有接口 才能进行代理, 代理后对象必须转换为接口类型  !!
     
    第二种 CGLIB(CodeGenerationLibrary)是一个开源项目
        * Spring使用CGlib 进行AOP代理, hibernate 也是支持CGlib(默认 使用 javassist )
     需要下载cglib 的jar包 (Spring 最新版本3.2 内部已经集成cglib ,无需下载cglib的jar )
        * 可以为目标类,动态创建子类,对目标类方法进行代理 (无需接口)
         
    Spring AOP 底层,会判断用户是根据接口代理还是目标类代理,如果针对接口代理 使用JDK代理,如果针对目标类代理 使用Cglib代理,无法复写final类,另外cglib二进制发型包放在classpath 
     
     
    2.使用注解完成spring AOP
    AOP 规范由 AOP 联盟组织(aopalliance) 来定义 , 最初目的采用代理方式,对目标方法进行增强
    定义了五种增强方式 (Advice )
    1) 前置通知 org.springframework.aop.MethodBeforeAdvice 
        在目标业务方法执行前 通知代码 (增强代码)
    2) 后置通知 org.springframework.aop.AfterReturningAdvice
        在目标业务方法返回后,执行通知代码
    3) 环绕通知 org.aopalliance.intercept.MethodInterceptor
        可以在 目标业务方法执行前 和 执行后 执行通知代码
    4) 异常抛出通知 org.springframework.aop.ThrowsAdvice
        在目标方法执行出现异常后,执行通知代码
    5) 引介通知 org.springframework.aop.IntroductionInterceptor
        * 与前四种不同,对目标类添加新的方法或者属性
        * 前四种都是方法级别的增强,引介通知是类级别的增强
     
    2.0准备spring包含的jar包
    2.1编写业务类
     
    package cn.jfree.aspectj;
     
    public class UserDao {
     
      public void save(){
          System.out.println("添加用户");
      }
      public void update(){
          System.out.println("更新用户");
      }
      public  void delete(){
          System.out.println("删除用户");
      }
      public void find(){
          System.out.println("查询用户");
      }
    }
    2.2 编写切面类
    /**************
    详细讲解:
     1.类加注解@Aspect
     2.切入点表达式execution(*返回值 类名*.方法名*(..))
     3.before可以有参数JoinPoint
     4.@AfterReturning returning必须和参数名称一致
    **************/
    package cn.jfree.aspectj;
     
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
     
    @Aspect
    public class AspectJTest {
        /**
         * 使用这种方式完成切入点配置
         */
        @Pointcut("execution(* cn.jfree.aspectj.UserDao.delete(..))")
        public void pointcut() {
        }
        /**
         * 配置切入点
         */
        @Before("execution(* cn.jfree.aspectj.UserDao.save(..))")
        public void before() {
            System.out.println("在保存之前执行");
        }
        /**
         *
         * @param joinpoint --切入点表达式的值
         */
        @Before("execution(* cn.jfree.aspectj.UserDao.save(..))")
        public void before(JoinPoint joinpoint) {
            System.out.println("在保存之前执行"+joinpoint);
        }
        /**
         *
         * @param joinpoint
         * @param returnVal 返回值必须与参数类型一致
         */
        @AfterReturning(value="execution(* cn.jfree.aspectj.UserDao.update(..))",returning="returnVal")
        public void afterReturning(JoinPoint joinpoint,Object returnVal){
            System.out.println("结果的返回值"+returnVal);
        }
        /**
         * 利用环绕通知可以实现日志管理,性能检测等...
         * @param point
         * @return
         */
        @Around("execution(* cn.jfree.aspectj.UserDao.find(..))")
        public Object around(ProceedingJoinPoint point) {
            long start = System.currentTimeMillis();
            System.out.println("方法执行前时间"+start);
            Object obj = null;
            try {
                obj = point.proceed();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            long end = System.currentTimeMillis();
            System.out.println("方法结束时间"+end);
            long exetime=end-start;
            System.out.println("方法执行时间"+exetime);
            return obj;
        }
        /**
         * 用于抛出异常
         * @param e
         */
        @AfterThrowing(value="execution(* cn.jfree.aspectj.UserDao.delete(..))",throwing="e")
        public void afterThrow(Throwable e){
            System.out.println(e.getMessage());
            //此处如果出现异常,不会执行
        }
        /**
         * 不管是否出现异常都会执行,相当于finally
         *
         */
        @After("AspectJTest.pointcut()")
        public void after(){
            System.out.println("不管是否出现异常都会执行,相当于finally");
        }
         
    }
     
     
    2.3 applicationContext.xml配置文件
     
    <!-- 开启自动代理 -->
    <aop:aspectj-autoproxy/>
     
    <!-- 业务类配置 -->
    <bean id="userDao" class="cn.jfree.aspectj.UserDao"></bean>
    <!-- 切面类配置 -->
    <bean id="myAspectJ" class="cn.jfree.aspectj.AspectJTest"></bean>
     
    2.4 编写测试类
     
    package cn.jfree.aspectj;
     
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
     
     
    public class AopTest {
       public static void main(String[] args) {
           ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
           UserDao userDao=(UserDao) applicationContext.getBean("userDao");
          //userDao.save();
         //  userDao.find();
        //   userDao.update();
           userDao.delete();
       }
    }
    3.Spring 动态AOP自定义标签
    3.1 在Spring中自定义注解标签
    package org.springframework.aop.config;
    public class AopNamespaceHandler extends NamespaceHandlerSupport {
     
        /**
         * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
         * '<code>config</code>', '<code>spring-configured</code>', '<code>aspectj-autoproxy</code>'
         * and '<code>scoped-proxy</code>' tags.
         */
        public void init() {
            // In 2.0 XSD as well as in 2.1 XSD.
            registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
            registerBeanDefinitionParser("aspectj-autoproxy", new                                           AspectJAutoProxyBeanDefinitionParser());
            registerBeanDefinitionDecorator("scoped-proxy", new                         ScopedProxyBeanDefinitionDecorator());
            // Only in 2.0 XSD: moved to context namespace as of 2.1
            registerBeanDefinitionParser("spring-configured", new                       SpringConfiguredBeanDefinitionParser());
        }
    }
    3.2 AspectJAutoProxyBeanDefinitionParser方法对aspectj-autoproxy进行解析
    package org.springframework.aop.config;
    class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
            //<aop:aspectj-autoproxy expose-proxy="false" proxy-target-class="false"/>
        public BeanDefinition parse(Element element, ParserContext parserContext) {
            AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
            extendBeanDefinition(element, parserContext);
            return null;
        }
     
        private void extendBeanDefinition(Element element, ParserContext parserContext) {
            BeanDefinition beanDef =
                    parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
            if (element.hasChildNodes()) {
                addIncludePatterns(element, parserContext, beanDef);
            }
        }
     
        private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
            ManagedList<TypedStringValue> includePatterns = new ManagedList<TypedStringValue>();
            NodeList childNodes = element.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                Node node = childNodes.item(i);
                if (node instanceof Element) {
                    Element includeElement = (Element) node;
                    TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
                    valueHolder.setSource(parserContext.extractSource(includeElement));
                    includePatterns.add(valueHolder);
                }
            }
            if (!includePatterns.isEmpty()) {
                includePatterns.setSource(parserContext.extractSource(element));
                beanDef.getPropertyValues().add("includePatterns", includePatterns);
            }
        }
     
    }
    3.3 注册类
        public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                ParserContext parserContext, Element sourceElement) {
              //注册AutoProxyCreator
            BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                    parserContext.getRegistry(), parserContext.extractSource(sourceElement));
            //属性 proxy-target-class expose-proxy
            useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
            //注册组件,用于监听
            registerComponentIfNecessary(beanDefinition, parserContext);
        }
     
    private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {
            Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
            if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
                //如果存在internalAutoProxyCreator注册类,根据类名判断
                BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
                if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                    //如果与当前类名不一致,需要根据优化级来判断选择哪个
                    int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                    int requiredPriority = findPriorityForClass(cls);
                    if (currentPriority < requiredPriority) {//注册类的类名优先级
                        apcDefinition.setBeanClassName(cls.getName());
                    }
                }
                //如果已经存在注册类,则不创建
                return null;
            }
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
            return beanDefinition;
        }
    强制使用cglib需要使用proxy-target-class="true"
     
    3.4 接口BeanPostProcessor
     真正创建代理是从getAdvicesAndAdvisorsForBean开始,
    获取代理的步骤:1)获取增强方法或者增强器
              2)根据获取的增强创建代理
     
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean != null) {
                //根据给定的beanClass和beanName生成key,格式为beanClass_beanName
                Object cacheKey = getCacheKey(bean.getClass(), beanName);
                //如果合适做代理,请生成代理对象
                if (!this.earlyProxyReferences.containsKey(cacheKey)) {
                    return wrapIfNecessary(bean, beanName, cacheKey);
                }
            }
            return bean;
        }
     
     
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
            //如果已经处理过了,无需增强
            if (this.targetSourcedBeans.containsKey(beanName)) {
                return bean;
            }
            //无需增强
            if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
                return bean;
            }
            //如果是基础设施类,或者配置了无需增强
            if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
             //如果获取增强方法,请创建代理
            // Create proxy if we have advice.
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
            if (specificInterceptors != DO_NOT_PROXY) {
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }
     
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
     
    3.5  获取增强类
          1)获取所有增强
          2)获取所有增强中适合bean的增强,并应用
        protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
            List<Advisor> candidateAdvisors = findCandidateAdvisors();
            List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
            extendAdvisors(eligibleAdvisors);
            if (!eligibleAdvisors.isEmpty()) {
                eligibleAdvisors = sortAdvisors(eligibleAdvisors);
            }
            return eligibleAdvisors;
        }
     
    实现思路:
    1)获取所有的beanName,在beanFactory中注册的所有类都找出来
    2)遍历所有的beanName,找到@Aspect的增强的类
    3)对标记为@Aspect进行增强器的提取
    4)将提取结果加入到缓存中
    public List<Advisor> buildAspectJAdvisors() {
            List<String> aspectNames = null;
     
            synchronized (this) {
                aspectNames = this.aspectBeanNames;
                if (aspectNames == null) {
                    List<Advisor> advisors = new LinkedList<Advisor>();
                    aspectNames = new LinkedList<String>();
                    String[] beanNames =
                            BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
                    for (String beanName : beanNames) {
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }
                        // We must be careful not to instantiate beans eagerly as in this
                        // case they would be cached by the Spring container but would not
                        // have been weaved
                        Class beanType = this.beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }
                        if (this.advisorFactory.isAspect(beanType)) {
                            aspectNames.add(beanName);
                            AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                                if (this.beanFactory.isSingleton(beanName)) {
                                    this.advisorsCache.put(beanName, classAdvisors);
                                }
                                else {
                                    this.aspectFactoryCache.put(beanName, factory);
                                }
                                advisors.addAll(classAdvisors);
                            }
                            else {
                                // Per target or per this.
                                if (this.beanFactory.isSingleton(beanName)) {
                                    throw new IllegalArgumentException("Bean with name '" + beanName +
                                            "' is a singleton, but aspect instantiation model is not singleton");
                                }
                                MetadataAwareAspectInstanceFactory factory =
                                        new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                                this.aspectFactoryCache.put(beanName, factory);
                                advisors.addAll(this.advisorFactory.getAdvisors(factory));
                            }
                        }
                    }
                    this.aspectBeanNames = aspectNames;
                    return advisors;
                }
            }
     
            if (aspectNames.isEmpty()) {
                return Collections.EMPTY_LIST;
            }
            List<Advisor> advisors = new LinkedList<Advisor>();
            for (String aspectName : aspectNames) {
                List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
                if (cachedAdvisors != null) {
                    advisors.addAll(cachedAdvisors);
                }
                else {
                    MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
                    advisors.addAll(this.advisorFactory.getAdvisors(factory));
                }
            }
            return advisors;
        }

    3. [文件] springORM源码分析.txt ~ 133B     下载(79)     

    1
    2
    3
    4
    5
    6
    7
    8
    1.JDBC连接数据库
    以Mysql为例
    1)获取jar包 mysql-conector-java*.jar
    2)注册驱动
    3)获取链接
    4)获取statement
    5)执行sql语句
    5)关闭流

    4. [文件] JDBC.txt ~ 6KB     下载(81)     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    1.JDBC批处理
    l业务场景:当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。
    l实现批处理有两种方式,第一种方式:
    ?Statement.addBatch(sql)
    l执行批处理SQL语句
    ?executeBatch()方法:执行批处理命令
    ?clearBatch()方法:清除批处理命令
     
    Connection conn = null;
     
    Statement st = null;
     
    ResultSet rs = null;
     
    try {
     
    conn = JdbcUtil.getConnection();
     
    String sql1 = "insert into user(name,password,email,birthday)
     
      values('kkk','123','abc@sina.com','1978-08-08')";
     
    String sql2 = "update user set password='123456' where id=3";
     
    st = conn.createStatement();
     
    st.addBatch(sql1);  //把SQL语句加入到批命令中
     
    st.addBatch(sql2);  //把SQL语句加入到批命令中
     
    st.executeBatch();
     
    } finally{
     
      JdbcUtil.free(conn, st, rs);
     
    }
     
     
     
    l采用Statement.addBatch(sql)方式实现批处理:
    ?优点:可以向数据库发送多条不同的SQL语句。
    ?缺点:
    ?SQL语句没有预编译。
    ?当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。例如:
     
      Insert into user(name,password) values(‘aa’,’111’);
     
      Insert into user(name,password) values(‘bb’,’222’);
     
      Insert into user(name,password) values(‘cc’,’333’);
     
      Insert into user(name,password) values(‘dd’,’444’);
     
     
     
    l实现批处理的第二种方式:
    ?PreparedStatement.addBatch()
     
    conn = JdbcUtil.getConnection();
     
    String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)";
     
    st = conn.prepareStatement(sql);
     
    for(int i=0;i<50000;i++){
     
    st.setString(1, "aaa" + i);
     
    st.setString(2, "123" + i);
     
    st.setString(3, "aaa" + i + "@sina.com");
     
    st.setDate(4,new Date(1980, 10, 10));
     
    st.addBatch();
     
    if(i%1000==0){
     
    st.executeBatch();
     
    st.clearBatch();
     
    }
     
    }
     
    st.executeBatch();
    l采用PreparedStatement.addBatch()实现批处理
    ?优点:发送的是预编译后的SQL语句,执行效率高。
    ?缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。
    2)关于批处理的思考
    在此笔记里,我们将看到我们如何可以使用像Statement和PreparedStatement JDBC API来批量在任何数据库中插入数据。此外,我们将努力探索一些场景,如在内存不足时正常运行,以及如何优化批量操作。
     
    首先,使用Java JDBC基本的API批量插入数据到数据库中。
     
    Simple Batch - 简单批处理
        我把它叫做简单批处理。要求很简单,执行批量插入列表,而不是为每个INSERT语句每次提交数据库,我们将使用JDBC批处理操作和优化性能。
     
    想想一下下面的代码:
     
    Bad Code
     String [] queries = {
        "insert into employee (name, city, phone) values ('A', 'X', '123')",
        "insert into employee (name, city, phone) values ('B', 'Y', '234')",
        "insert into employee (name, city, phone) values ('C', 'Z', '345')",
     };
    Connection connection = new getConnection();
    Statement statemenet = connection.createStatement();
     for (String query : queries) {
        statemenet.execute(query);
    }
    statemenet.close();
    connection.close();
     
    这是糟糕的代码。它单独执行每个查询,每个INSERT语句的都提交一次数据库。考虑一下,如果你要插入1000条记录呢?这是不是一个好主意。
     
    下面是执行批量插入的基本代码。来看看:
     
    Good Code
     
    Connection connection = new getConnection();
    Statement statemenet = connection.createStatement();
     for (String query : queries) {
        statemenet.addBatch(query);
    }
    statemenet.executeBatch();
    statemenet.close();
    connection.close();
     
      
     
    请注意我们如何使用addBatch()方法,而不是直接执行查询。然后,加入所有的查询,我们使用statement.executeBatch()方法一次执行他们。没有什么花哨,只是一个简单的批量插入。
     
    请注意,我们已经从一个String数组构建了查询。现在,你可能会想,使其动态化。例如:
     
    import java.sql.Connection;
    import java.sql.Statement;
    //...
    Connection connection = new getConnection();
    Statement statemenet = connection.createStatement();
    for (Employee employee: employees) {
        String query = "insert into employee (name, city) values('"
                + employee.getName() + "','" + employee.getCity + "')";
        statemenet.addBatch(query);
    }
    statemenet.executeBatch();
    statemenet.close();
    connection.close();
     
    请注意我们是如何从Employee对象中的数据动态创建查询并在批处理中添加,插入一气呵成。完美!是不是?
     
    等等......你必须思考什么关于SQL注入?这样动态创建的查询SQL注入是很容易的。并且每个插入查询每次都被编译。
     
    为什么不使用PreparedStatement而不是简单的声明。是的,这是个解决方案。下面是SQL注入安全批处理。
     
    SQL Injection Safe Batch - SQL注入安全批处理
    思考一下下面代码:
     
    import java.sql.Connection;
    import java.sql.PreparedStatement;
     //...
    String sql = "insert into employee (name, city, phone) values (?, ?, ?)";
    Connection connection = new getConnection();
    PreparedStatement ps = connection.prepareStatement(sql);
     for (Employee employee: employees) {
        ps.setString(1, employee.getName());
        ps.setString(2, employee.getCity());
        ps.setString(3, employee.getPhone());
        ps.addBatch();
    }
    ps.executeBatch();
    ps.close();
    connection.close();
     
    看看上面的代码。漂亮。我们使用的java.sql.PreparedStatement和在批处理中添加INSERT查询。这是你必须实现批量插入逻辑的解决方案,而不是上述Statement那个。
     
    这一解决方案仍然存在一个问题。考虑这样一个场景,在您想要插入到数据库使用批处理上万条记录。嗯,可能产生的OutOfMemoryError:
     
    java.lang.OutOfMemoryError: Java heap space
    com.mysql.jdbc.ServerPreparedStatement$BatchedBindValues.<init>(ServerPreparedStatement.java:72)
    com.mysql.jdbc.ServerPreparedStatement.addBatch(ServerPreparedStatement.java:330)
    org.apache.commons.dbcp.DelegatingPreparedStatement.addBatch(DelegatingPreparedStatement.java:171)
     
    这是因为你试图在一个批次添加所有语句,并一次插入。最好的办法是将执行分批次。看看下面的解决方案
     
    Smart Insert: Batch within Batch - 智能插入:将整批分批
    这是一个简单的解决方案。考虑批量大小为1000,每1000个查询语句为一批插入提交。
     
    String sql = "insert into employee (name, city, phone) values (?, ?, ?)";
    Connection connection = new getConnection();
    PreparedStatement ps = connection.prepareStatement(sql);
    final int batchSize = 1000;
    int count = 0;
    for (Employee employee: employees) {
        ps.setString(1, employee.getName());
        ps.setString(2, employee.getCity());
        ps.setString(3, employee.getPhone());
        ps.addBatch();
        if(++count % batchSize == 0) {
            ps.executeBatch();
        }
    }
    ps.executeBatch(); // insert remaining records
    ps.close();
    connection.close();
     
    这才是理想的解决方案,它避免了SQL注入和内存不足的问题。看看我们如何递增计数器计数,一旦BATCHSIZE 达到 1000,我们调用executeBatch()提交。

    5. [文件] spring框架的使用.txt ~ 32KB     下载(72)     

    6. [文件] SpringMVC源码.txt ~ 7KB     下载(54)     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    1.什么是SpringMVC
     
    SpringMVC模式提供了构建web的mvc模板,支持策略模式,支持多种视图技术,例如JSP,Velocity,Tiles
    ,iText和POI.SpringMVC分离了控制器,模板对象,分派器,以及处理程序对象的角色,这种分离可以使它们更容易定制.
     
    2.Spring的概述
     
    SpringMVC是基于Servlet功能实现的,通过实现Servlet接口的DispatcherServlet来封装核心功能实现,通过请求分派给处理程序,同时带有可配置的处理程序映射,视图解析,本地语言,主题解析,文件上传支持.默认的处理程序是非常简单的Controller接口,只有一个方法ModelAndVide handlerRequest(request,response),Spring提供了一个控制器层次结构,可以派生子类.如果应用程序需要处理用户输入表单,可以继承AbstractFormController.如果需要要把多页输入处理到一个表单,可以继承AbstractWizardFormContrloller.
     
    SpringMVC从请求中搜集数据,对传入的参数进行验证,Controller对系统流程进行控制管理,将结果返回不同的视图,不同的视图提供不同的方案,拦截器,上传文件等功能
    核心组件有:
    DispatcherServlet
     
    Controller
    handlerMapping
     
    ModelAndViewViewResolverInterceptors
     
    3.SpringMVC的解决的问题
    1)将web页面的请求传给服务器
    2)根据不同的请求结果处理不同的逻辑单元
    3)返回处理结果数据并跳转至响应的页面
     
    3.1 SpringMVC的工作流程
          1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
          2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
          3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)
           4.  提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
          HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
          数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
          数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
          数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
          5.  Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
          6.  根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
          7. ViewResolver 结合Model和View,来渲染视图
          8. 将渲染结果返回给客户端。
    //思考 :SpringMVC为什么使用一个DispacherServlet来处理所有servlet请求
            前端控制器模式
     
    4.SpringMVC快速体验
     1)在web.xml中配置dispatcherServlet
            <!-- 配制spring分发器servlet -->
             
    <servlet>
                    <servlet-name>action</servlet-name>
                 
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        </servlet>
            <servlet-mapping>
                 
        <servlet-name>action</servlet-name>
                        <url-pattern>*.action</url-pattern>
             
    </servlet-mapping>
      2)创建Spring配置文件/WEB-INF/action-servlet.xml
       Spring mvc需要一个配置文件:
     
        位置:默认情况下在WEB-INF下
     
        命名规则:servlet的名称 + “-”+ servlet.xml
     
     
     
       
    5.SpringMVC的DispatcherServlet解析
     
    6.
     
     
    初始化
        protected void initStrategies(ApplicationContext context) {
            initMultipartResolver(context);
            initLocaleResolver(context);
            initThemeResolver(context);
            initHandlerMappings(context);
            initHandlerAdapters(context);
            initHandlerExceptionResolvers(context);
            initRequestToViewNameTranslator(context);
            initViewResolvers(context);
            initFlashMapManager(context);
        }
     
     
    1)初始化MultipartResolver
    在Spring中,MultipartResolver主要用于文件上传.默认情况下Spring中是没有Multipart请求处理的,因为一些开发者想要自己处理这些请求,如果想要使用Multipart,需要在配置文件中添加MultipartResolver解析器,如果添加配置则会用于处理Multipart的能力,还能实现用户的文件上传等功能.
    MultipartResolver就是在initMultipartResolver中加入到DispatcherServlet中的
        /**
         * Initialize the MultipartResolver used by this class.
         * <p>If no bean is defined with the given name in the BeanFactory for this namespace,
         * no multipart handling is provided.
              //如果不提供处理器,则不会产生对应的multipart处理器
         */
        private void initMultipartResolver(ApplicationContext context) {
            try {
                this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
                if (logger.isDebugEnabled()) {
                    logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
                }
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Default is no multipart resolver.
                this.multipartResolver = null;
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
                            "': no multipart request handling provided");
                }
            }
        }
     
    因为之前已经完成配置文件的解析,所以只需要注册ApplicationContext中提供的getBean方法即可,然后初始化multipartResolver中的multipartResolver变量
    文件上传的配置
    <bean id="multipartResolver"     class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  <property name="maxUploadSize" value="102400000"></property></bean>2)初始化localeResolver
     
    3)
    4)初始化handlerMappings
    5)初始化handlerAdapters
     
    7.重要组件介绍
     
    7.1 HandlerMapping介绍
    1)BeanNameUrlHandlerMapping  (默认)
     
    2)SimpleUrlHandlerMapping
    3)ControllerClassNameHandlerMapping
     
     
    7.2 Controller介绍
     
    1)ParameterizableViewController(参数控制器)
    2)AbstractCommandController(命令控制器)
      
     
    * 需要继承AbstractCommandController类,并重写handle方法
    * 通过构造方法注册命令类和命令名称,如:
        public MyCommandController(){
             
        //注册命令类
             
        this.setCommandClass(Person.class);
             
        //命令名称
             
        this.setCommandName("person");
         
    }
    3)FormController(表单控制器)
    * 需要继承SimpleFormController类,并重写doSubmitAction方法
    * 通过构造方法注册命令类和命令名称,如:
        public MyFormController(){
             
        this.setCommandClass(Person.class);
             
        this.setCommandName("person");
         
    }
     
    * 在spring配置文件中对表单控制器进行配置,如: <!-- 表单控制器 -->
         
    <bean id="myFormController" name="/form.action" class="cn.joker.controller.MyFormController">
             
        <property name="successView" value="success"/>
             
        <property name="formView" value="personForm"/>
         
    </bean>
    8 SpringMVC 基于注解开发
      @Controller
     @RequestMapping
       请求方式
     参数   传递
    返回值
    9.Spring 拦截器
    实现HandlerInterceptor接口
           
        preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
         
    postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
    ?
    afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。

    7. [代码][Java]代码     

    1
    springmvc的使用

    8. [文件] SpringMVC使用示例.txt ~ 11KB     下载(32)     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    1.SpringMVC入门示例
     
    1.1 web.xml配置文件
     
      <!-- springmvc核心控制器 -->
            <servlet>
            <servlet-name>springmvc</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:springmvc-servlet.xml</param-value>
            </init-param>
        </servlet>
        <servlet-mapping>
            <servlet-name>springmvc</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
     
     
    1.2 springmvc-servlet.xml配置文件
     
        <bean id="controlllerTest" name="/hello.do" class="cn.cunzhang.springmvc.ControllerTest"></bean>
          
        <!-- springmvc配置文件 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <property name="prefix" value="/jsp/"></property>
         <property name="suffix" value=".jsp"></property>
        </bean>
     
    1.3 controller控制代码
     
    public class ControllerTest extends AbstractController{
     
        @Override
        protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
                HttpServletResponse arg1) throws Exception {
            System.out.println("Hello World");
            return new  ModelAndView("success");
        }
     
    }
     
     
    请求为配置文件中的hello.do
    请求路径为/jsp/success.jsp  字符串拼接的过程为prefix+ viewName + suffix
     
    2.常用的handlerMapping
     
    第一种  org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
    根据Bean中的name进行映射
     
    配置文件:默认不配置
    或者如下
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
    <bean id="controlllerTest" name="/hello.do" class="cn.cunzhang.springmvc.ControllerTest"></bean>
    通过bean中name为/hello.do映射而成
     
    源码如下:
        protected String[] determineUrlsForHandler(String beanName)
        {
            List urls = new ArrayList();
            if(beanName.startsWith("/"))
                urls.add(beanName);
            String aliases[] = getApplicationContext().getAliases(beanName);
            String as[];
            int j = (as = aliases).length;
            for(int i = 0; i < j; i++)
            {
                String alias = as[i];
                if(alias.startsWith("/"))
                    urls.add(alias);
            }
     
            return StringUtils.toStringArray(urls);
        }
    }
     
     
    第二种 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
     
    配置文件:
        <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
           <property name="mappings">
           <props >
            <prop key="/hello.do">controlllerTest</prop>
           </props>
          </property>
        </bean>
    <bean id="controlllerTest"  class="cn.cunzhang.springmvc.ControllerTest"></bean>
     
    通过key-value 映射获取路径
     
    源码如下: 
         有一个方法为 setMappings,所以可以使用 mappings属性
     
        protected void registerHandlers(Map urlMap)
            throws BeansException
        {
            if(urlMap.isEmpty())
            {
                logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
            } else
            {
                String url;
                Object handler;
                for(Iterator iterator = urlMap.entrySet().iterator(); iterator.hasNext(); registerHandler(url, handler))
                {
                    java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next();
                    url = (String)entry.getKey();
                    handler = entry.getValue();
                    if(!url.startsWith("/"))
                        url = (new StringBuilder("/")).append(url).toString();
                    if(handler instanceof String)
                        handler = ((String)handler).trim();
                }
     
            }
        }
     
    第三种 org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping
     
    配置文件
        <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
        <bean   class="cn.cunzhang.springmvc.TestController"></bean>
     
    通过类名来访问 testControlller.do 
    类名首字母需要小写
    源码如下:
     
        protected String[] generatePathMappings(Class beanClass) {
            StringBuilder pathMapping = buildPathPrefix(beanClass);
            String className = ClassUtils.getShortName(beanClass);
            String path = (className.endsWith(CONTROLLER_SUFFIX) ?
                    className.substring(0, className.lastIndexOf(CONTROLLER_SUFFIX)) : className);
            if (path.length() > 0) {
                if (this.caseSensitive) {
                    pathMapping.append(path.substring(0, 1).toLowerCase()).append(path.substring(1));
                }
                else {
                    pathMapping.append(path.toLowerCase());
                }
            }
            if (isMultiActionControllerType(beanClass)) {
                return new String[] {pathMapping.toString(), pathMapping.toString() + "/*"};
            }
            else {
                return new String[] {pathMapping.toString() + "*"};
            }
        }
    3.常用的控制器 Controller
     
    第一种 参数控制器 org.springframework.web.servlet.mvc.ParameterizableViewController
    配置文件:
        <bean name="/tosuccess.do" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
          <property name="viewName" value="success"></property>
        </bean>
     
    源码如下: 配置viewName
        protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
            throws Exception
        {
            return new ModelAndView(getViewName());
        }
     
    第二种:命令控制器  org.springframework.web.servlet.mvc.AbstractCommandController.class
     
    命令控制器的写法:
     
    配置文件:
     
        <bean id="commonController" name="/tocommon.do" class="cn.cunzhang.springmvc.CommonController">
         <property name="commandClass" value="cn.cunzhang.jbug.model.User"></property>
        </bean>
     
    CommonController 代码:
     
    public class CommonController extends AbstractCommandController{
     
        @Override
        protected ModelAndView handle(HttpServletRequest httpservletrequest,
                HttpServletResponse httpservletresponse, Object obj,
                BindException bindexception) throws Exception {
               User user= (User) obj;
               System.out.println(user);
            return new ModelAndView("success");
        }
     
    }
     
     
    请求参数:tocommon.do?userId=1&UserName=cunzhang
    后台会获取到参数,不区分首字母大小写
    User [userId=1, userName=cunzhang, userPassword=null, loginTime=null, logonTime=null]
     
    第三种:表单控制器 org.springframework.web.servlet.mvc.SimpleFormController
     
    配置文件:
     
        <bean id="formController" name="/form.do" class="cn.cunzhang.springmvc.FormController">
          <property name="commandClass" value="cn.cunzhang.jbug.model.User"></property>
          <property name="formView" value="form"></property>
           <property name="successView" value="success"></property>
        </bean>
     
    表单 form.jsp
     
    <body>
    <form action="form.do" method="post">
    id<input type="text" name="userId"></input> <br/>
    姓名<input type="text" name="userName"></input> <br/>
    密码<input type="password" name="userPassword"></input> <br/>
    <input type="submit" value="提交"></input> <br/>
    </form>
    </body>
     
    代码:
     
    public class FormController extends SimpleFormController {
     
        @Override
        protected void doSubmitAction(Object obj) throws Exception {
            User user=(User) obj;
            System.out.println(user);
            super.doSubmitAction(obj);
        }
         
    }
     
    post方式可以提交,不支持get方式提交
     
    4.注解开发
     
    1.配置文件
     
       <mvc:annotation-driven/>    //可以去掉,因为下面已经包含了
        <context:component-scan base-package="cn.cunzhang.springmvc"></context:component-scan>
        <!-- springmvc配置文件 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <property name="prefix" value="/jsp/"></property>
         <property name="suffix" value=".jsp"></property>
        </bean>
     
    注解 @Controller
    注解 @RequestMapping
     
    代码一:  简单的请求,返回视图
     
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
     
    @Controller
    public class SimController {
       @RequestMapping("/hello.do")
       public String hello(){
           //返回的是viewName
           return "success";
       }
    }
     
    代码二: 接受请求,从HttpServletRequest请求中获取
     
       @RequestMapping("/toUser.do")
       public String toUser(HttpServletRequest request){
          String name= request.getParameter("name");
           System.out.println(name);
           return "success";
       }
     
    代码三:直接获取参数列表  toUserName.do?userName=cunzhang
        参数名必须匹配
       @RequestMapping("/toUserName.do")
       public String toUserName(String userName){
           System.out.println(userName);
           return "success";
       }
     
    代码四:多个参数传递 toUserall.do?userName=cunzhang&id=1&password=123
     
       @RequestMapping("/toUserall.do")
       public String toUserall(String userName,int id,String password){
           System.out.println("用户名"+userName+" 用户id"+id +"  用户密码"+password);
           return "success";
       }
       //
       注意特殊类型***  比如前台checkbox,接受方式使用  String[] checkbox
       后台获取的checkbox为 A,B
       //
       注意特殊类型 Date解析
          //日期类型格式装换器,会进行进制转换
       @InitBinder
       public void dateBinder(ServletRequestDataBinder binder){
           binder.registerCustomEditor(Date.class, new CustomDateEditor(new       SimpleDateFormat("yyyy-MM-dd"),true));
       }
           
     
     
    代码五:参数为对象 toUserobj.do?userName=cunzhang&userId=1&userPassword=123
     
      @RequestMapping("/toUserobj.do")
       public String toUserobj(User user){
           System.out.println(user);
           return "success";
       }
     
    注意: 如果出现多个类型
      @RequestMapping("/toUserobj.do")
       public String toUserobj(User user1,User user2){
           System.out.println(user1);
               System.out.println(user2);
           return "success";
       }
    两者都能获取到参数
     
    注意: 如果出现多个对象,但是对象中含有相同的属性
    比如 User中含有name ,Person中含有name
      @RequestMapping("/toUserobj.do")
       public String toUserobj(User user1,Person user2){
           System.out.println(user1);
               System.out.println(user2);
           return "success";
       }
    两者都能获取到参数,即user1中有name值, user2中也会有name值
     
    代码六 :数据提交和访问
     
       @RequestMapping("/toUsermap.do")
       public ModelAndView  toUsermap(User user){
           Map<String,Object> map=new HashMap<String,Object>();
           //相当于 request.setAtribute("u",user);
           map.put("u", user);
           System.out.println(user);
           return new ModelAndView("success",map);
       }
     
    返回值获取 EL表达式 ${u.userName}
     
    代码七:同六  视图和对象分离
     
       @RequestMapping("/toUserview.do")
       public String  toUserview(User user,Model model){
           model.addAttribute("u", user);
           return "success";
       }
     
       @RequestMapping("/toUserview.do")
       public String  toUserview(User user,Map<String,Object> map){
           map.put("u",user);
           return "success";
       }
     
    代码八:以流的形式使用ajax输出
     
       @RequestMapping("/toAjax.do")
       public void  toAjax(User user,HttpServletResponse response){
           String s="json字符串"+user;
           try {
            response.getWriter().write(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
       }
     
       @RequestMapping("/toAjaxpw.do")
       public void  toAjaxpw(User user,PrintWriter pw){
           String s="json字符串"+user;
           pw.write(s);
       }
     
    代码九:请求跳转
     
       @RequestMapping("/redirectAction.do")
       public String redirectAction(){
           return "redirect:toAjax.do";
               //路径 需要加上命名空间
       }
  • 相关阅读:
    爬虫
    Django
    python多线程
    python基础
    深度学习_1_Tensorflow_1
    人工智能_5_决策树_随机森林
    人工智能_4_k近邻_贝叶斯_模型评估
    人工智能_3_机器学习_概述
    Python re 模块
    Python函数式编程
  • 原文地址:https://www.cnblogs.com/developer-ios/p/5327378.html
Copyright © 2020-2023  润新知