`
xcllch
  • 浏览: 13619 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
最近访客 更多访客>>
社区版块
存档分类
最新评论

Web开发教程3-理解Spring设计模式

阅读更多

spring设计模式

 

 

程序员的春天来了!在这章中,您将开始接触Spring,学习Spring基础知识。并将看到Spring在实现OCP原则上所做的努力,接触到为实现OCP原则所产生的两个设计模式:DI依赖及IoC控制反转。此外,在最后,您还将学习到Spring在使用时应注意的问题。

什么是Spring以及使用它的意义

Spring框架十分受欢迎,并且发展迅速。其成功原因很大程度上源于它的设计思想。Spring框架的核心思想是 IoC及DI 。用句简单的话来解释,就是让程序的各个组件之间独立开来,每个零部件只要接口规格一致,就可以自由更换。这就使得应用了Spring框架的项目变得非常灵活。当然,如果仅仅只有这点优势,Spring也不会取得如此大的成功。除了使用了很好的设计思想,Spring还提供一套非常完整且实用的工具箱,并且这套工具箱秉承一种哲学:别人做得好的,直接拿来用,并在上层提供更方便的功能;别人做得不好的,自已做,并做到最好。因为使用了IoC及DI模式,Spring框架的各个部件都可以自由更换,因此它可以随时调整,保持每一个工具都十分优秀。

Spring既然被称为框架(Framework),就说明它包含了您在开发过程中要用到了各种工具,使Java开发人员有一整套可使用的工具包,不必再从轮子造起。在下图中展示了Spring提供的工具箱:

除了IoC核心以外,Spring在上层提供的工具涉及到J2EE领域的方方面面。在本文的后续部分,会陆续介绍DAO、ORM、JEE、WEB、AOP这几块的使用。

什么是IoC及DI

我们已经学习了OCP法则,那么如何才能保证您的代码遵守了OCP法则呢? Martin Fowler 提出了一种设计模式,叫做Dependency Injection,简称DI,中文叫做依赖注入。而通过使用这种模式实现了IoC,即Inversion Of Control,中文翻译成控制反转。通过这种模式,可以使项目符合OCP的设计原则。而Spring最核心的理念就是IoC及DI,并在这个设计思想上提供了一大套工具箱。名词比较抽象,下面直接通过实例来看一下其具体含义。

Spring的基本使用方式

现在制作一个用户听收音机的程序,程序中有两个类:用户User,收音机Radio。主程序的逻辑为用户使用收音机:

用户有姓名及收音机两个属性。收音机有一个use()方法。下面来看具体实现:

 

 

package demo;  

    

 public class Radio {  

    

    public String use() {  

         return "RADIO";  

     }  

 } 
下面是用户类的实现1:


 package demo;  

    

 public class User {  

     private String username;  

    

     private Radio radio;  

    

     public Radio getRadio() {  

         return radio;  

     }  

    

     public void setRadio(Radio radio) {  

         this.radio = radio;  

     }  

    

     public String getUsername() {  

         return username;  

     }  

    

     public void setUsername(String username) {  

         this.username = username;  

     }  

    

 } 
1 在讲解OCP法则时,讲过类的属性要封装,因此User类的username及radio属性要声明为private,而使用getter及setter方法去操作它们。

用户类中有两个属性:姓名,收音机。现在开始实现业务逻辑,即用户使用收音机:

 
package demo;  

    

 public class UserPlayRadio {  

    

     public static void main(String[] args) {  

         User user = new User();  

         Radio radio = new Radio();  

         user.setUsername("Peter");  

         user.setRadio(radio);  

         System.out.println(user.getUsername() + " is using " + user.getRadio().use());  

            

     }  

    

 } 
首先创建一个用户,然后创建一个收音机,并把这个收音机交给用户。最后,用户取得收音机,并播放它。系统最终返回结果:

 Peter is using RADIO 
这个设计似乎没什么问题,可是没过多久,客户跑过来找您,说这个程序需要添加一个功能:User除了使用收音机以外,还要使用电视。这下麻烦了,这个程序中用户包含的属性固定是收音机。如果还要添加看电视机的功能,除去添加电视机类别Tv以外,还必须修改User类,在其中添加电视机的属性。这样太不合理了,用户应该有能力去使用各种各样的电器。可是到了代码里,多了一个Tv,User类也必须随之更改。在这种情况下,可以使用接口来优化设计,将User对Radio及可能的Tv类别的依赖关系调整过来。

首先定义一个接口类别:电器Appliance。这个接口规定一个功能:use(),即所有的电器都可以被使用:

 package demo;  

 public interface Appliance {  

     public String use();  

 } 
接下来是改造User类别,将Radio属性去掉,代之以接口Appliance:

 package demo;  

  public class UserV2 {  

     private String username;    

     private Appliance appliance;  

     public Appliance getAppliance() {  

         return appliance;  

     }  

    

     public void setAppliance(Appliance appliance) {  

         this.appliance = appliance;  

    }  

    

     public String getUsername() {  

         return username;  

     }  

    

     public void setUsername(String username) {  

         this.username = username;  

     }  

    

 } 
这样用户并不知道它将使用什么样的电器,即用户对收音机的依赖关系被消除了,这种模式叫做’控制反转’。下面需要做的是在运行时,把用户要使用的Appliance实体类(Radio或Tv)通过set方法放进去,即依赖注入。不过现在先别急,还要实现一个新的类别:电视Tv。它实现Appliance接口。同样地,改造已有的Radio类别,使之实现Applicance接口:

 package demo;  

    

 public class Tv implements Appliance {  

    

     public String use() {  

         return "TV";  

     }  

 } 

 package demo;  

    

 public class RadioV2 implements Appliance{  

    

     public String use() {  

         return "RADIO";  

     }  

 } 
工作还没有完,业务逻辑’用户使用收音机’也应该做出修改,变成’用户使用电器’,至于具体使用什么电器,则由主程序在运行时注入,下面让用户分别使用收音机及电视机:

 
package demo;  

    

 public class UserPlayAppliance {  

    

     public static void main(String[] args) {  

         UserV2 user = new UserV2();  

         user.setUsername("Peter");  

   

         RadioV2 radio = new RadioV2();  

    

         user.setAppliance(radio);  

         System.out.println(user.getUsername() + " is using " 

                 + user.getAppliance().use());  

    

         Tv tv = new Tv();  

         user.setAppliance(tv);  

         System.out.println(user.getUsername() + " is using " 

                 + user.getAppliance().use());  

     }  

    

 } 
跑起来玩一下,看看系统的输出:

 Peter is using RADIO  

 Peter is using TV 
可以看到,用户听了收音机,也看了电视机。在代码中,分别将Radio及Tv赋给user,并且user不关心是什么电器,都可以拿过来play。通过应用IoC及DI模式,使系统附合了OCP法则。User类既保持了它的使用开放性(可以使用新加的Tv类别),也保持了修改的闭合性(新加的Tv类不会导致User类的变化)2

2 还记得在OCP一节中介绍的口诀吗?这里就是 层层之间用接口 的原则体现。

好的,原理讲完了。那么,Spring到底能帮您干些什么呢?简单来说,Spring最最核心的部分就是帮您把代码里user.setAppliance(radio)这样的工作给移到了配置文件中完成了。下面讲讲如何使用Spring。

首先需要在项目中制作一个Spring的配置文件,这个配置文件是XML格式的:

 
<?xml version="1.0" encoding="UTF-8"?>  

 <beans xmlns="http://www.springframework.org/schema/beans" 

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

     xmlns:p="http://www.springframework.org/schema/p" 

     xsi:schemaLocation="  

 http://www.springframework.org/schema/beans  

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  

     <bean id="peter" class="demo.UserV2" p:username="Peter" 

         p:appliance-ref='radio' />  

     <bean id="tom" class="demo.UserV2" p:username="Tom" 

         p:appliance-ref='tv' />  

    

     <bean id="radio" class="demo.RadioV2" />  

     <bean id="tv" class="demo.Tv" />  

 </beans> 
对于这个配置文件,其关键内容是声明了一个名字为peter的bean:

 <bean id="peter" class="demo.UserV2" p:username="Peter" 

         p:appliance-ref='radio' /> 
这个bean为UserV2的实例。两个p元素是将UserV2的两个属性username及appliance注入。配置文件中的’p:username’就相当于调用代码的setUsername()进行属性具体值的注入。Spring读到这个配置文件时,就会调用UserV2中的setUsername方法把属性注入,p:appliance也是一样的道理。

此外,您可以发现,username及appliance的注入方式还稍有不同。由于username是一个String类型的属性,因此我们把需要的值直接写进去就可以了。这里我们指定用户的名字为’Peter’。请注意字串类型的属性值是用双引号括起来的。对于appliance,由于这个属性对应我们定义的Appliance接口,因此我们需要注入一个Appliance的实例。在Spring的配置当中,我们需要注入一个Appliance的bean。因此,在配置文件中我们定义了这个bean:

 <bean id="radio" class="demo.RadioV2" /> 
RadioV2是一个实现了Appliance接口的实体类,这个bean的id为radio。在peter中我们将radio这个bean注入到了appliance属性当中。请注意,如果要引用其它的bean,需要在属性后面加’-ref’,并用单引号引用bean的id:

 p:appliance-ref='radio' 
同样的道理,还声明了一个`tom’的用户,不同的是为这个用户注入的电器是Tv而不是Radio。关于Spring配置文件的语法,相信您已经有了一个初步的认识,可能一开始还不习惯,我们随着阅读Spring的配置文件量不断增加以及不断地亲自实践,对它的语法就会慢慢习惯。

此外,配置文件的开始,是Spring的命名空间声明。什么是命名空间呢?您可以把它理解为Java代码中的package。XML文件中的命名空间声明就相当于java代码中对于的package的import。在Java代码中,只有引用了相关的package,才能使用package中提供的类。同样地,只有引入了相关的命名空间,才能使用命名空间中定义的XML元素。在我们的配置文件中,引入了最基本的bean元素,以及简化配置语言的p元素:

 xmlns:p="http://www.springframework.org/schema/p"  

     xsi:schemaLocation="  

 http://www.springframework.org/schema/beans  

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" 
这样,我们在配置文件中就可以使用bean。此外,我们在bean中便可以使用p元素来简化配置。什么叫做’用p元素来简化配置’呢?举个例子您就明白了,比如下面这个声明:

 <bean id="peter" class="demo.UserV2" p:username="Peter" 

         p:appliance-ref='radio' /> 
如果不用p元素,那么上面这个配置默认的Spring配置写法应该是这样的:

 <bean id="peter" class="demo.UserV2">  

     <property name="username" value="Peter" />  

     <property name="appliance" ref="radio" />  

 </bean> 
怎么样,是不是使用p元素后,配置文件简单多了?在配置文件中完成了注入工作后,我们接下来看看如何使用’peter’及’tom’这两个User,下面撰写一个新的UserPlayAppliance类别:

 
package demo;  

    

 import org.springframework.context.ApplicationContext;  

 import org.springframework.context.support.ClassPathXmlApplicationContext;  

    

 public class UserPlayApplianceV2 {  
    

     public static void main(String[] args) {  

         ApplicationContext ctx = new ClassPathXmlApplicationContext  

                 "config.xml");  

         UserV2 peter = (UserV2) ctx.getBean("peter");  

         System.out.println(peter.getUsername() + " is using " 

                 + peter.getAppliance().use());  

    

         UserV2 tom = (UserV2) ctx.getBean("tom");  

         System.out.println(tom.getUsername() + " is using " 

                 + tom.getAppliance().use());  

    }  

 } 
在上面的代码中,首先系统将配置文件 config.xml 读进Spring的系统上下文类别 ApplicationContext 在这里使用了 ClassPathXmlApplicationContext 进行读取工作,从名字就可以看得很清楚这个类从class路径中读取系统配置文件。除此以外,Spring还提供多种加载类,在后续文章中陆续介绍。

在第11行,从ApplicationContext的getBean()方法提取出配置好的用户`peter’,此时Spring会帮您创建配置文件中的bean,即User、Radio,并按照配置,通过调用user的setAppliance()方法把radio注入。15-17行同样道理。跑一下这个程序,看下系统输出:

 Peter is using RADIO  

 Tom is using TV 
以上说明了Spring的基本使用方法及背后所蕴涵的设计思想。在下一节,您将看到如何使用Java 5的最新Annotation特性,简化代码及配置。

Property注入与Constructor注入
我们在前一节通过Spring的配置文件,把某个Bean的某个属性通过此属性的setter方法注入到这个Bean当中。这样的注入方式在Spring称做Property注入。例如:

 <bean id="tom" class="demo.UserV2" p:username="Tom" p:appliance-ref='tv' /> 
username与appliance是通过UserV2中的setter方法被注入的:

 
package demo;  

    

 public class UserV2 {  

     private String username;  

    

     private Appliance appliance;  

 ...  

     public void setAppliance(Appliance appliance) {  

         this.appliance = appliance;  

     }  

    

     public void setUsername(String username) {  

         this.username = username;  
     }  

    

 } 
除了Property注入以外,Spring还支持Constructor注入。即通过建构方法,在Class被创建时,把Bean注入。我们来看看这样的方式。首先创建一个Bean,这个Bean在建构方法接收两个属性的注入:

 package demo;  
    

 public class Bean {  

     private BeanA beanA;  

    

     private BeanB beanB;  

    

     public Bean(BeanA beanA, BeanB beanB) {  

         super();  

         this.beanA = beanA;  

         this.beanB = beanB;  

     }  

    

 } 
下面我们在Spring配置文件中,通过Bean的建构方法把BeanA及BeanB注入:

 <bean id="bean" class="Bean">  

         <constructor-arg ref="beanA" />  

         <constructor-arg ref="beanB" />  

</bean>  

   

 <bean id="beanA" class="BeanA" />  

 <bean id="beanB" class="BeanB" /> 
请注意, contructor-arg 的书写顺序要与建构方法中的参数顺序一致。如果beanA,beanB在 constructor-arg 中的顺序颠倒了,那么配置文件中的beanA将被注入Bean的beanB,配置文件中的beanB将被注入Bean的beanA,导致程序出错,无法执行。

基于Constructor的注入与基于Property的方式在达到的效果和使用目的上没什么区别。但大多数情况下,使用基于Property方法的注入可以使配置文件看起来更加清淅,也不涉及顺序的问题。但使用Constructor方法也有它的好处,如果需要在某个类的建构方法中加入一些与注入息息相关的逻辑代码时,将不得不采取这种方式。在这一方面没什么原则可言。只要您多多使用,找到自己最顺手的方式就可以了。在下一节当中,我们介绍另一种注入方式,也是Spring 2.5中的新方式:基于Java标记的Bean自动绑定。

使用Spring Annotation进行自动绑定
在Java 5中,Annotation特性被标准化,并且允许用户定义自己的标记,Spring利用这一新特征,提供了一系列方便好用的Annotation。

回过头再来看一下上一节的样例。在配置文件中,有如下的声明:

 <bean id="peter" class="demo.UserV2" p:username="Peter" 

         p:appliance-ref='radio' /> 
通过 p:appliance-ref=`radio' ,radio这个bean被注入到user中。为了配合注入,在User类中必须提供getter及setter方法,供Spring使用:

 private Appliance appliance;  

    

 public Appliance getAppliance() {  

     return appliance;  

 }  

    

 public void setAppliance(Appliance appliance) {  

     this.appliance = appliance;  

 } 
Spring从2.5版本开始支持Java Annotation简化装配流程。下面看一下使用标记的新配置文件及代码。首先是User类别的修改:

 
package demo;  

    

 import org.springframework.beans.factory.annotation.Autowired;  

    

 public class UserV3 {  

     private String username;  

    

     @Autowired 

     private Appliance appliance;  

    

     public String getUsername() {  

         return username;  

     }  

    

     public void setUsername(String username) {  

         this.username = username;  

     }  

    

     public Appliance getAppliance() {  

         return appliance;  

     }  

    

 } 
首先是appliance的setter方法被省掉了。在第8行有一个Spring的标记@Autowired。这个标记的作用是将配置文件中,与Appliance同类别的bean自动加载进来。看一下配置文件:

 
<?xml version="1.0" encoding="UTF-8"?>  

 <beans xmlns="http://www.springframework.org/schema/beans" 

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

     xmlns:p="http://www.springframework.org/schema/p" 

     xsi:schemaLocation="  
 http://www.springframework.org/schema/beans  

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  

    

     <context:annotation-config />  

    

     <bean id="peter" class="demo.UserV3" p:username="Peter" />  

    

     <bean class="demo.RadioV2" />  

    

 </beans> 
关于这个配置文件,有以下几点要说:

•在第9行,新添了一个 context:annotation-config 的元素,这一标记告诉Spring,在代码中使用了Annotation的特性。这样代码中的@Autowired标记才会生效。
•从第11行可以看到,原来的 p:appliance-ref 的设置省去了。因为在代码中appliance属性上声明了@Autowired标记,Spring会在配置中查找与appliance同类别的bean,并进行自动绑定。因此只需声明下面的bean即可。
•在第13行声明了radio bean,它实现了appliance接口,因此会被自动绑定3}。bean的识别id也可以不写了。
3 细心的读者可能会问:如果有多个类都实现了appliance接口,Spring该如何得知绑绑定哪一个实现类?不必着急,请继续往下看。

完成了配置,下面我们来看一下新的逻辑代码:

 
package demo;  

    

 import org.springframework.context.ApplicationContext;  

 import org.springframework.context.support.ClassPathXmlApplicationContext;  

    

 public class UserPlayApplianceV3 {  

    

     public static void main(String[] args) {  

         ApplicationContext ctx = new ClassPathXmlApplicationContext(  

                 "configV2.xml");  

         UserV3 peter = (UserV3) ctx.getBean("peter");  

         System.out.println(peter.getUsername() + " is using " 

                 + peter.getAppliance().use());  

     }  

    

 } 

可以看到使用bean的方法没有任何变化,底层的自动绑定并没有影响前端的使用。系统输出如下:

 Peter is using RADIO 
此时会有另一种情况:如果配置文件中有两个bean都实现了appliance接口该怎么办?此时系统该绑定哪一个?答案是系统不能决定,会抛出错误。因此,当配置中有两个相同类别的bean时,需要为其指定类似命名空间的参数,叫做qualifier。下面是一个配置例子:

 
<?xml version="1.0" encoding="UTF-8"?>  

 <beans xmlns="http://www.springframework.org/schema/beans" 

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

     xmlns:p="http://www.springframework.org/schema/p" 

     xsi:schemaLocation="  

 http://www.springframework.org/schema/beans  

 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  

    

     <context:annotation-config />  

    

     <bean id="peter" class="demo.UserV4" p:username="Peter" />  

    

     <bean class="demo.RadioV2">  

         <qualifier value="radio" />  

     </bean>  

    

     <bean class="demo.Tv">  

         <qualifier value="tv" />  

     </bean>  

 </beans> 
在配置中有两个同属于一个Appliance类别的bean:Radio及Tv,但为它们指定了各自的qualifier。这样,在用户绑定的时候声明使用哪一个,就不会造成混淆:

 
package demo;  

    

 import org.springframework.beans.factory.annotation.Autowired;  

 import org.springframework.beans.factory.annotation.Qualifier;  

    

 public class UserV4 {  

     private String username;  

    

     @Autowired 

     @Qualifier("radio")  

     private Appliance appliance;  

    

     public String getUsername() {  

         return username;  

     }  

    

     public void setUsername(String username) {  

         this.username = username;  

     }  

    

     public Appliance getAppliance() {  

         return appliance;  

     }  

    

 } 
下面运行一下业务逻辑:

 package demo;  

    

 import org.springframework.context.ApplicationContext;  

 import org.springframework.context.support.ClassPathXmlApplicationContext;  

    

 public class UserPlayApplianceV4 {  

    

     public static void main(String[] args) {  

         ApplicationContext ctx = new ClassPathXmlApplicationContext     "configV3.xml");  

         UserV4 peter = (UserV4) ctx.getBean("peter");  

         System.out.println(peter.getUsername() + " is using " 

                 + peter.getAppliance().use());  

    

     }  

    

 } 
这一版代码与前一版没什么区别,仅仅是配置文件使用刚刚做好的的configV3.xml,输出如下:

1 Peter is using RADIO 
可以看到,虽然配置中有两个同类别的bean,在qualfier的帮助下,Spring可以正确地绑定需要的bean。这种绑定方式的好处是配置及代码大大地简化了,但付出的代价是User类别只能绑定Appliance某种具体的实现类,如果想从Radio切换到Tv,就需要在 User.java 中将@Qualifier切换至’tv’。这是代码简化付出的代价。

Spring在使用中需要注意的问题
在上一节使用Spring时,用 ClassPathXmlApplicationContext 把配置读取进来,并从中取bean。用下面这个代码看看Spring的这样一个动作的开销是多大:

 package demo;  

    

 import org.springframework.context.support.ClassPathXmlApplicationContext;  

    

 public class ShowTimeConsumingByLoadingContext {  

     private static long start = 0;  

    

     private static long end = 0;  

    

     private static final int TIMES = 100;  

    

     public static void main(String[] args) {  

         long timer = 0;  

         for (int i = 0; i < TIMES; i++) {  

             start = System.currentTimeMillis();  

             new ClassPathXmlApplicationContext("config.xml");  

             end = System.currentTimeMillis();  

    

             timer += end - start;  

         }  

         System.out.println("the average time of load is: " + timer / TIMES  

                 + "ms");  

   

     }  

 } 
为了使评测结果更加客观,将计时器分成两个:start使end。并且将其声明为static,在系统加载时为其分配内存,这样声明使两个变量的系统开销影响降至最低。并且在第19行,计时后再计算,减法开销可忽略。最后,使用循环的方式,进行100次的配置加载,最后取平均值。在我的机器上运行结果为为: 40ms。我的机器配置为:内存2GB为667 MHz DDR2 SDRAM、CPU为2.1 GHz Intel Core 2 Duo。可见这个开销是不可以忽视的。

如果在使用Spring时,在代码中有很多这样的加载点,那么每一次用户调用时,都会有一次开销。这在J2EE的世界中是不可接受的。因为WEB应用天生就是多线程的,如果100个用户同时访问您的项目,这时每个线程里的程序类都要执行:

1 new ClassPathXmlApplicationContext("xxx.xml") 
那么这个配置就要被加载100次,系统开销是非常大的。因此,您在构建J2EE工程时,必须要避免以这种形式使用Spring,否则它将成为系统瓶颈。正确的方法是在J2EE项目启动时,将所有的配置一次性统一加载到静态内存中,各个线程共享并由Spring控制bean的生命周期。在第二部分将介绍这种加载方式。

小结
本文介绍了OCP原则,DI及Spring的设计模式,并介绍了一种基于Annotation自动绑定方法。请大家记住那条口诀: 层层之间用接口,类的属性要封装

 

分享到:
评论

相关推荐

    Spring高级之注解驱动开发视频教程

    视频详细讲解,需要的小...n 设计模式-RowMapper的策略模式 n 高级应用-NamedParameterJdbcTemplate的使用 n 源码分析-TransactionTemplate n 源码分析-DataSourceUtils n 源码分析-TransactionSynchronizationManager

    Java Web开发实例大全

    Java Web开发实例大全(提高卷)筛选、汇集了Java Web开发从基础知识到高级应用各个层面的大量实例及源代码,共有600个左右,每个实例及源代码按实例说明、关键技术、设计过程、详尽注释、秘笈心法的顺序进行了分析...

    J2EEWEB开发教程

    J2EEWEB开发教程 第一章 J2EE的基本概念和规范 第二章 Web服务器和Web应用服务器 第三章 利用Tomcat创建和发布Web应用 第四章 Java Servlet 第五章 Java Servlet Page 第六章 JDBC技术 第七章 Struts与MVC设计模式 ...

    蚂蚁课堂(每特学院)第一期-Java高端培训视频教程

    教程目录: ├─0001-多线程快速入门.zip ├─0002-多线程之间实现同步.zip ├─0003--多线程之间通讯.zip ├─0004--Java并发编程.zip ├─0005--数据交换格式与SpringIOC底层实现.zip ├─0006--自定义注解与设计...

    《精通Spring2.X企业应用开发详解》随书源码1-15章

    此外,我们还对Spring技术所涉及到的各种Java技术、Java设计模式进行了适时的介绍,通过这些背景知识的准备,读者在理解Spring的各项原理时将不会有任何的障碍。 =============================================...

    Java Web程序设计教程

    5.1.2mvc设计模式 81 5.1.3struts2框架的mvc架构 82 5.2struts2概览 84 5.2.1struts2的工作流程 84 5.2.2struts2的简单应用 85 5.3struts2基础 87 5.3.1action详解 88 5.3.2结果与视图 91 5.3.3struts.xml的...

    《精通Spring2.X企业应用开发详解》20-23

    此外,我们还对Spring技术所涉及到的各种Java技术、Java设计模式进行了适时的介绍,通过这些背景知识的准备,读者在理解Spring的各项原理时将不会有任何的障碍。 =============================================...

    《精通Spring2.X企业应用开发详解》16-19章

    此外,我们还对Spring技术所涉及到的各种Java技术、Java设计模式进行了适时的介绍,通过这些背景知识的准备,读者在理解Spring的各项原理时将不会有任何的障碍。 =============================================...

    Java Web开发实例大全(基础卷) 完整pdf扫描版[179MB]

    Java Web开发实例大全(提高卷)筛选、汇集了Java Web开发从基础知识到高级应用各个层面的大量实例及源代码,共有600个左右,每个实例及源代码按实例说明、关键技术、设计过程、详尽注释、秘笈心法的顺序进行了分析...

    21天学通Java Web开发.pdf

    《21天学通Java Web开发》是Java Web开发的基础教程,针对没有接触过或还不是特别熟悉Java Web开发的读者,详细介绍了Java Web开发的基础概念及技术要点。全书分为6篇共21章内容,第一篇为Java Web基础篇,介绍了...

    asp.net知识库

    Web开发: 使用URL重写WEB主题切换 如何在Asp.Net1.1中实现页面模板(所谓的MasterPage技术) Tool Tip 示例(FILTER版) Tool Tip示例 (htc版) 一个.net发送HTTP数据实体的类 按键跳转以及按Enter以不同参数提交,及...

    java8集合源码分析-Notes:笔记

    设计模式 编程规范 开发框架 前端框架 后端框架 服务器软件 Web服务器 Web应用服务器 操作系统 计算机基础知识 Linux基础 Linux进阶 Linux优化 数据库体系 Oracle DB2 Mysql 开发工具 集成开发工具 代码管理工具 ...

    ServletJSPSpringMVC初学指南.zip

    Spring MVC 是一个广泛应用于GUI 开发的设计模式,是目前业界主流的Web 开发框架,也是一种热门的开发技能。 本书分两大部分,详细介绍了Servlet 和JSP 的核心技术,以及Spring MVC 的实践应用。

    WEB开发必备几乎包含所有参考资料

    100道逻辑思维趣题,ajax框架:dwr》实战(包括整合),Ajax中英文对照手册,CSS2 – Quick Reference ...WINDOWS脚本技术,华为内部程序设计培训,全新java基础实践教程,设计模式手册,网页设计配色常识,正则表达式系统教程

    springmybatis

    1. 现阶段,你可以直接建立java 工程,但一般都是开发web项目,这个系列教程最后也是web的,所以一开始就建立web工程。 2. 将 mybatis-3.2.0-SNAPSHOT.jar,mysql-connector-java-5.1.22-bin.jar 拷贝到 web工程的...

    驾校-驾校系统-驾校系统源码-驾校管理系统-驾校管理系统java代码-基于springboot的驾校系统-驾校项目代码-代码

    navicat16破解版安装教程驾校-驾校系统-驾校系统源码-驾校管理系统-驾校管理系统java代码-驾校系统设计与实现-基于springboot的驾校系统-基于Web的驾校系统设计与实现-驾校网站-驾校网站代码-驾校平台-驾校平台代码-...

    最新SpringBoot项目游戏分享网站.zip

    基于Spring Boot的游戏分享网站是一个**提供游戏内容分享和交流平台的Web应用**。以下是对该项目的具体介绍: 1. **开发语言与技术**: ...通过实际操作和使用该系统,可以加深对现代Web开发技术的理解和应用。

    最新SpringBoot项目人事管理系统.zip

    基于Spring Boot的人事管理系统是一个**为现代企业设计的人力资源管理解决方案**。以下是对该项目的具体介绍: 1. **技术架构**: ...通过实际操作和使用该系统,可以加深对现代Web开发技术的理解和应用。

    最新SpringBoot项目在线外卖系统.zip

    基于Spring Boot的在线外卖系统是一个为餐饮业定制的软件解决方案,它通常包括系统管理后台和移动端应用两大部分。以下是对该系统的具体介绍: ...通过实际操作和使用该系统,可以加深对现代Web开发技术的理解和应用。

    java8集合源码分析-tools:常用工具分享

    设计模式 - 快速搭建 Spring 项目的简易框架,上手快 JUST RUN - Examples : Spring Boot 教程、技术栈示例代码,快速简单上手教程 - 快速生成 Spring 项目 - Web 服务器 - Java 包管理器 - 一款 Web 服务器,类似...

Global site tag (gtag.js) - Google Analytics