09Spring

来源:互联网 发布:网络lw代表什么意思 编辑:程序博客网 时间:2024/05/23 18:31


SpringMybatis01





————————————————————————————————


架构师:深入研究框架的设计思想,研究如何改造




Spring
——开源的,简化企业级应用开发的框架


Rod Johnson
——古典音乐博士




javaEE API:
。servlet
。jsp
。ejb
。jms
。jta
。jdbc
...
3个特点:
1.简化开发
2.管理对象
3.集成其它框架
spring可以将其它的一些框架集成进来
(比如,集成用于 任务调度的框架Quartz)。
即“不发明重复的轮子”。
(比如,可以利用spring继承mybatis(mybatis是一个用来访问数据库的框架 ))
4.?
5.?










1. spring是什么?
是一个开源的用来简化应用开发的框架。


简化开发


spring对常用的api做了封装和简化(比如,对jdbc 做了封装,使用spring jdbc来访问数据库,就不再 需要考虑获取连接和关闭连接了)。


管理对象


spring提供了一个容器,帮我们创建对象以及建立对象 之间的依赖关系。这样做的好处是,降低对象之间的 耦合度,方便代码的维护。


集成其它框架


spring可以将其它的一些框架集成进来(比如,集成用于 任务调度的框架Quartz)。即“不发明重复的轮子”。


































————————————————————————————————————————
1.
maven导包,
搜索spring-webmvc


选择:
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>3.2.8.RELEASE</version>
2.添加配置文件
将applicationContext.xml放到src/main/resource目录下




创建Spring:
先创建Spring类,一句话启动Spring
2.创建实体类
3.在applicationContext.xml内配置


/*
* 此行代码的作用:通过容器获得要创建的对象(注意:getBean方法的第一个参数是bean的id)
* Class对象:
Student.class:是Student在方法区中对应的class对象
*/
//Student stu1 = (Student)ac.getBean("stu1");  //强转,或加参数使用java反射机制
//使用java反射机制
Student stu1 =ac.getBean("stu1",Student.class); 


——————————————————————————————


》》》》》java反射机制简单举例:


MessageBean mb = new MessageBean("abc");
mb.sendMsg();


java底层如何处理:


java把os划分给的内存空间为3部分


栈:(一个线程一个stack)保存对象“abc”的首地址,如111
堆:对象"abc"
方法区:class对象


看方法区有没有MessageBean的class对象
class对象:编译后在硬盘上会有.class文件,但是内存里面没有,jvm调用类加载器去硬盘找到该类字节码文件,
加载到内存中变为一个对象。硬盘中是一个字节码文件,到内存中就变成了一个对象,class放到方法区


通过变量找到对象,对象通过指针指向方法区
每一个堆都有一个指针,指向方法区的方法,如sendMsg()


如:
Student stu1 =ac.getBean("stu1",Student.class); 
这里的Student.class就是class对象


Student.class:是Student在方法区中对应的class对象
——————————————————————————————————————————
静态工厂方法(了解)
<!-- factory-method属性:指定一个静态方法。
Spring容器会调用该方法来创建对象
Calendar c = Calendar.getInstance(); -->
<bean id="cal1" class="java.util.Calendar" factory-method="getInstance"></bean>






————————————————————————








// Student stu1 =ac.getBean("stu1",Student.class);  
// System.out.println(stu1);


Calendar cal1 = ac.getBean("cal1",Calendar.class);
System.out.println(cal1);


为何已经注释了没调用stu1也会输出Student()呢?






————————————————————————————————————————————————————


作用域:


1.默认情况下,容器只会创建一个实例(单例)






——————————————————————————————————————


junit
单元测试工具,用来看模块有没有错误
导包:maven搜:junit
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>


src/test/java新建一个包和类java类






window--》showview——outline
在test1方法上右键选择run asjunit
绿色表示成功,红色错误


有了junit就不必每次写main方法测试了


在xml中:
<!-- scope属性:用来指定作用域,缺省值是
singleton(单例),如果值是prototype(原型),则会创建多个对象 -->
<bean id="sb1" class="basic.ScopeBean" scope="prototype"></bean>




——————————————————————————————————


生命周期相关的两个方法
初始化方法:对象被调用之前获取资源,只执行一次
销毁方法:(释放资源),只执行一次。作用域必须是单例的,如果设置为原型,销毁方法就失效了


__________________________________________________________________________________________________


延迟加载(LazyBean类演示)




lazy-init="true"缺省值是false,true的时候表示延迟加载




——————————————————————————————————————————


IOC(Inversion Of Control 控制反转)是目标


DI (Dependency Injection 依赖注入)是手段


举例:
容器:外包公司








依赖注入有一个条件:bean必须是容器创建的


<bean id="b1" class="ioc.B"></bean>
<bean id="a1" class="ioc.A">
<property name="b" ref="b1"/>  
调用对象A的属性b,会自动把属性的第一个字母大写,然后变成了setB
ref:传参,因为在类A里面的setB()是下面这样的:


public void setB(B b) {
System.out.println("setB()");
this.b = b;
}
所以,ref这里是把id为b1的B注入
</bean>




————————————————————————————————————————


initializationError


>>>>看看junit的测试类中的该方法的上面是不是遗漏了@Test




作用域scope的值不是boolean类型
scope="singleton" 默认的,单例,只有一个对象
scope="prototype" 作用域变更为原型prototype后则多例,生成多个对象


延迟加载才是boolean的


lazy-init="false"  ---->默认的  
lazy-init="true"




——————————————————————————————————————————————


创建对象的三种方式:
无参构造器<bean id="" class="">
静态工厂方法<..factory-method="">调用static修饰的方法,
如Calendar.getInstance-->类名.的可看出是静态方法
实例工厂方法<..factory-bean="">  如Calendar的getTime()方法,该方法是无参的


作用域:
scope,
----singleton默认
----prototype 则生成多个对象
生命周期:
init-method destory-method



!!spring一启动,先把默认单例的singleton的对象创建出来,不管有没有调用
延迟加载(lazy-init="true/false")
----》设置为true就是spring一启动并不会马上创建,而是等调用getBean才创建该对象






DI的方式:
--1.set注入
--2.构造器方式注入




——————————————————————————————————————————————


day02


————————————————
2.构造器方式注入






<bean id="b1" class="ioc.B"></bean>
<!--constructor-arg:表示采用构造器方式注入。其中,index属性指定参数的下标(从0开始)  -->
<bean id="a1" class="ioc.A">
<!-- 传给构造器的第几个参数 -->
<constructor-arg index="0" ref="b1"/>
<constructor-arg index="1" ref="c1"/>
</bean>




——————————————————————————————————————
自动装配(了解)


默认情况下,容器不会自动装配
可以设置autowire属性,让容器依据某些规则来注入相应的对象
 autowire属性值有如下几个:
——1.byName
——2.byType
——3.constructor




容器会检查restaurant内,去找


——————————————————————————————————
byName:


<bean id="wt1" class="auto.Waiter"/>
<!-- autowire:表示让容器自动装配
byName:容器以属性名也就是类Restaurant内的wt属性作为bean的id来查找符合条件的bean,
找到之后,调用对应的set方法来注入。注意,如果找不到符合条件的bean,注入null
也不可能找到多个,因为id是唯一的 
-->
<bean id="rest" class="auto.Restaurant" autowire="byName"/>




——————————————————————————————————


byType
autowire="byType" 则跟id没关系,而是直接找类型Waiter


<bean id="wt1" class="auto.Waiter"/>
<bean id="wt2" class="auto.Waiter"/>
<!-- autowire:表示让容器自动装配
byName:容器以属性名也就是类Restaurant内的wt属性作为bean的id来查找符合条件的bean,
找到之后,调用对应的set方法来注入。注意,如果找不到符合条件的bean,注入null
也不可能找到多个,因为id是唯一的 
byType:容器以属性类型作为bean的类型来查找符合条件的bean,找到之后,调用对应的set方法来注入
如果找到多个,则会出错
constructor:容器以属性类型作为bean的类型来查找符合条件的bean,找到之后,调用 
对应的构造器来注入
 
-->


<bean id="rest" class="auto.Restaurant" autowire="constructor"/>
使用构造器注入当然Restaurant类得有有参的构造器,以及创建了waiter对象,否则也是空的
————————————————————————————


(6) 注入基本类型的值


使用value属性即可


<!-- 注入基本类型的值:

-->
<bean id="vb1" class="value.ValueBean">
<property name="name" value="胡八一"></property>
<property name="age" value="30"></property>
<property name="interest">
<list>
<value>钓鱼</value>
<value>做饭</value>
<value>看电视</value>
<!-- List允许重复 -->
<value>看电视</value>
</list>
</property>
<property name="city">
<set>
<value>北京</value>
<value>上海</value>
</bean>


__能否追加ref?___________________________________________________________










(7) 注入集合类型的值 (支持4中类型:List /Set /Map /Properties)




Properties是一种特殊的map,key和value都是字符串
读取:
<util:properties id="config" location="classpath:config.properties"/>
————————————————————————————
(8) 引用的方式注入集合类型的值








XML的命名空间:
namespace


<%@taglib uri="http://xxxx/" prefix="c"%>


<c:if>
</c:if>


这个uri就是命名空间,防止重名的冲突




————————————————————————————————————————————————————


<!-- 使用Spring表达式去读取其它的bean的属性,就像jstl/el一样 -->
<bean id="sb1" class="value.SpelBean">
<property name="name" value="#{vb1.name}"></property>
</bean>


找vb1为id的类,调取getName方法


<property name="pageSize" value="#{config.pagesize}"></property>


这里的pagesize是文件里的key




注意单标签/双标签
——————————————————————————————


注解:




xml配置:
<context:component-scan base-package="annocation"/>




<!--配置组件扫描
一旦加了这个组件,容器就会扫描这个包以及其子包下面的所有的类。
如果这个类前面添加了特定的注解(比如@component),
则容器会将这个类纳入容器管理(相当于配置了一个bean,其中,bean的id默认值等
于首字母小写之后的类名
 -->
其中base-package=""只需要填写包名


——————————————————
编程步骤:
1 。在类前添加特定的注解,比如@Component。
2.。在配置文件中,使用component-scan来配置组件扫描




注解标记: 描述:
@Component 通用注解 (来自于Spring框架)
@Named 通用注解 (来自用sun)
@Repository 持久化层组件注解
@Service 业务层组件注解
@Controller 控制层注解


如果不清楚哪个层,就写Component
虽然有了组件扫描,但是xml也还能用bean,
比如
让容器创建一个Date
不是自己写的,而是别人给的bean,就还需要自己配置bean
大量的bean不需要在xml写了,只需要注解




————————————————————————————————
依赖注入相关的两个注解


——@Autowired/@Qualifier  正统的Spring的注解
—— a .支持set方式注入和构造器方式注入
—— b.set方法注入
——@Resource(重点)


————————————————————————


//容器会自动装配,通过byType。去找id为wt的Waiter类型。为了防止有多个id,
//使用@Qualifier指定id
@Autowired
public void setWt(@Qualifier("wt")Waiter wt) {
System.out.println("setWt() ");
this.wt = wt;
}


但是放到set方法可以执行多个条件,而放到放到属性里,只是单纯的赋值
——————————————————
public class Hotel {
//其实可以放到属性里,只是单纯的赋值
@Autowired
@Qualifier("wt")
private Waiter wt;

public Hotel() {
System.out.println("Hotel()");
}


下面的set的方法就不需要了
其底层用的还是java反射机制




c.构造器方式注入




————————————————————————————————————————


被调用的类需要get方法,如day02的value包的ValueBean.java




——————————————————————————


day03
回顾:




1.什么是容器
2.启动
3.创建对象:无参构造器/静态工厂方法/实例工厂方法
4.作用域: singleton / prototype
5.生命周期
6.延迟加载


IOC 对象的依赖关系由容器来管理 A--> B
1.DI依赖注入
2.set方法 /构造器 (xml用<constructor-arg index="">)
3.自动装配  autowire(byName/byType/contructor)
4.基本类型值的注入(在spring中string被当作基本类型,在java中string被当作对象)
5.集合类型值的注入
List/Set/Map/Properties
<util:list id="xxxBean"></list>
<property name="" ref=""/>
<util:properties id="" location="classpath:xxx.properties"/>


6.spring表达式(注意:被调用的类里面必须有get方法,如此案例的ValueBean.java)
#{vb1.name}  
#{vb1.interest[0]}
#{vb1.score['英语']}
7.注解的方式
1.组件扫描
@Component @Service @Repository @Controller
1.类加注解
2.配置文件加<Context:component-scan base-package="包名"/>
2.
@scope
@Lazy
@PostConstruct
@PreDestroy
3.依赖注入相关的两个注解
@Autowired  /@Qualifier (支持set和构造方法注入)
@Resource(只支持set方式注入)实际中用set更多,而且这个更简单,因此更常用




—————————————————————————————


@Resource(name="wt") //不用Resource的name属性指明的话也会默认按照byType找
public void setWt(Waiter wt) {
this.wt = wt;
}




@Resource可以加在set前面也可以在属性前。其中,name属性用来指定被注入的bean的id




##  @Value注解 (可以加载set前面也可在属性前面)
——注入spring表达式的值
——注入基本类型的值
注: 可以将@Value添加到set方法前面也可在属性前面






@Value("胡八一")
private String name;

//使用spring表达式取访问另一文件的属性
@Value("#{config['jdbc.pagesize']}")
注意:这里使用外部文件在xml也还是要配置:
<util:properties id="config" location="classpath:config.properties"/>






—————————————————————————————————————


springmvc
1.springmvc是什么
可以重复使用的控制器,简化,提高开发效率。mvc大框架中的一个mvc框架


(2)五大组件
DispatcherServlet (前端控制器)


接受请求,依据HandlerMapping的配置调用相应的 模型来处理。


HandlerMapping


包含了请求路径与模型的对应关系。


Controller (处理器)


负责处理业务逻辑。


ModelAndView


封装了处理结果。
注:处理结果除了数据之外,还可能有视图名。


ViewResolver (视图解析器)


DispatcherServlet依据ViewResolver的解析, 调用真正的视图对象来生成相应的页面。




————————————————————————————


1.DispatcherServlet收到请求之后,依据HandlerMapping的配置调用响应的处理器来处理。
2.处理器将处理结果封装成ModelAndView,然后返回给DispatcherServlet
3.DispatcherServlet依据ViewResolver的解析,调用相应的视图来生成相应的页面




编程步骤:
1.导包
2.添加一个spring的配置文件
3.配置DispatcherServlet
4.写Controller(处理器)
5.写jsp
6.配置HandlerMapping,VeiwResoler
DispatcherServlet会负责启动spring容器,但要知道sping的配置文件,
因此在<param-init>需要指定




public class HelloServlet implements Controller {
....
public ModelAndView handleRequest(HttpServletRequest req, 
HttpServletResponse res) throws Exception {

return null;


}
}






return ModelAndView(“hello.jsp") //.jsp就限定死了,如果需要用其他的视图层技术如freemaker等
,这里则无法更改,耦合度太高


return ModelAndView(“hello")  //正确的做法!!




HandlerMapping是一个接口,使用其实现类SimpleUrlHandlerMapping




<!-- 配置视图解析器 -->
<bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/> 
<property name="suffix" value=".jsp"/> 
</bean




tomcat一启动就会把servlet实例化




练习:
/spring01-lab/toLogin.do




__________________________________________________________________________________


在spring-mvc.xml中:


<!-- 配置HandlerMapping -->


<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.do">hc</prop>
</props>
</property>
</bean>
<!-- 配置处理器 -->
<bean id="hc" class="controller.HelloServlet"/>
<!-- 配置视图解析器 -->
<bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/"/> 
    <property name="suffix" value=".jsp"/> 
</bean> 



注意: <bean id="hc" class="controller.HelloServlet"/>


这一行的class就是main目录的java类




————————————————————————————————————————————————————


## 4)使用注解简化配置
1.导包
2.添加一个spring的配置文件
3.配置DispatcherServlet
4.写Controller(处理器) 一个处理器包含多个方法
要求: 1.不用实现Controller接口
2.可以添加多个方法
3.方法名不做要求,返回值可以是ModelAndView,也可以是String(只有视图名,没有数据时)
4.将@Controller添加到类名前
5.将@RequestMapping添加到类名前或者方法前,而不要在springmvc.xml里面配置bean


5.写jsp








使用注解方式,登录Login.html
spring的方式创建连接池
——?当xml配置好属性,读取了config.properties的数据之后,如何输出??




——————————————————————————————————


注意:@RequestMapping("/toLogin.do")一定要放在对应的方法前面,
无论是无数据响应的用String方法只返回给视图层的方法
或者有数据响应的ModelAndView类型的方法,
都一样。
而不能是类名前面,就算
是只有一个方法也不行。


加类名前面只有:
//@RequestMapping("/demo")//模块化,表明的demo下的请求用这个方法








————————————————————————————————
eclipse设置的validate可以把验证disable,加快运行速度
day04
回顾:
springmvc:
mvc框架, 简化基于mvc架构的web应用程序的开发
五大组件
DispatcherServlet----核心,前端控制器
HandlerMapping
Controller-----处理器
ModelAndView处理结果和视图名
ViewResolver视图解析器


——————————————————————————————————————


1.读取请求参数值
1)第一种方式 通过request对象(最灵活)
将request对象作为方法的入参即可
2)第二种方式:通过@RequestParam
将@RequestParam添加到方法的形参前面即可
注意:@RequestParam负责指定请求参数名与形参的对应关系
如:public String login2(String adminCode,@RequestParam("pwd")String password){


3)第三种方式:封装成javabean(会自动给该bean内的各个属性赋值)(当参数数量比较多的时候)
step1.写一个java类,封装各个请求参数
step2.将该java类作为方法的形参类型




2.向页面传值
1)第一种方式:使用请求对象request
将数据绑定到request对象,然后转发给jsp
2)第二种方式: 使用ModelAndView对象
将数据封装到ModelAndView对象,然后作为方法的返回值
@RequestMapping("/login5.do")
/*
* 使用ModelAndView向页面传值
*/
public ModelAndView login5(AdminParam ap){
System.out.println("login5()");


String adminCode = ap.getAdminCode();

//将处理结果封装到ModelAndView
Map<String,Object> data = new HashMap<String,Object>();
//绑定到请求,相当于执行了request.setAttribute("adminCode",adminCode)
//根据key查找的
data.put("adminCode",adminCode); //el表达式跟"adminCode"一样

ModelAndView mav= new ModelAndView("index",data);

return mav;
}
3)第三种方式:使用ModelMap对象(重点关注)
将该对象作为方法的形参,将数据添加到该对象里面即可


@RequestMapping("/login6.do")
/*
* 使用ModelMap向页面传值
*/
public String login6(AdminParam ap,ModelMap mm){
System.out.println("login6()");
//将结果/处理数据添加到mm,到时候前端控制器会从controller获取
//相当于执行了request.setAttribute(”adminCode",adminCode);
mm.addAttribute("adminCode",ap.getAdminCode());
return "index";
}


4)第四种方式:使用session对象(session的生存时间比request长)
/*
* 使用session对象向页面传值
*/
public String login7(AdminParam ap,HttpSession session){
System.out.println("login7()");
session.setAttribute("adminCode",ap.getAdminCode());

return "index";

}


1/2/3都是一样的,实际都是request
以后使用request,用完释放,session时间长,占用内存空间,除非有重定向才用session,因为重定向有2个请求,request明显不行




3.重定向
1)方法的返回值String
return "redirect:重定向地址";
比如: return "redirect:toIndex.do";


2)方法的返回值是ModelAndView
RedirectView rv = new Redirect("toIndex.do")
ModelAndView mav = new ModelAndView(rv);






4.系统分层(扩展)跟mvc的分层不一样
举例:如企业的决策层,管理层,执行层
1)如何分层
表示层: 表示逻辑,请求分发
业务层: 业务逻辑的处理
持久层: 数据库访问
注意:
a.上一层通过接口调用下一层的服务
b.下一层的实现发生任何改变,不影响上一层






M:业务逻辑 业务层,持久层
V:表示逻辑(数据展现,操作界面)
C:控制逻辑(协调)


数据加工,数据库访问












————————————————————————————


@RequestMapping("/login.do")
/*
* DispatcherServlet在调用处理器的方法之前,会分析该方法的签名,
* 如果发现该方法有一个request对象,则会将该request对象作为参数传递进来
* 也可以加响应对象,session等等。用的是java的反射机制
*/
public String login(HttpServletRequest request){ //login被DispatcherServlet调用
System.out.println("login()");
String adminCode = request.getParameter("adminCode");
String pwd = request.getParameter("pwd");
String valiCode = request.getParameter("valiCode");
return "index";


————————————————————————————————————————————————


绝对路径:
链接地址/重定向/表单提交 从应用名开始写
如: <form action="<%request.getContextPath()%>/login3.jsp> </form>
转发从应用名之后开始写








也有把controller叫做二级控制器,如LoginController




mvc是属于表示层的一种架构




企业不用dbcp,而是C3P0
DBCP性能差


driverClassName:com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3309/sampledb
username=root


————————————————————————————————————————————————


day05:


} catch (SQLException e) {
//打印异常信息。发生异常后通常做2件事
//1.保留现场,记录日志,异常写到文件
e.printStackTrace();
/*2.看异常能否恢复(架构师的思路),
*如果能够恢复,则立即恢复;如果不能够恢复(如数据库服务停止,一般称这样的异常为系统异常),
*则提示用户稍后重试
*/
//如果是运行时异常,则不需要在方法后面声明throws,但是
//如果是其他异常如SQL,那么连带其接口也要抛这个jdbc的SQL异常,如果后续变更需求,不使用该
//技术,那么代码接口都需要更改!!!
throw new RuntimeException(e);




————————————————————————————————————


AdminDAOJdbcImpl测试报错adminDAO找不到,要看xml是不是包名用子包了




应用异常:用户输入错误,不输入等属于用户错误的异常


ApplicationException通常是自己创建一个异常类




————————————————————————————————


package com.tarena.netctoss.service;
/*
 * 应用异常类
 * 用户在使用系统时,因为一些不正确的操作引起的异常,比如输入了错误的账号
 * */
public class ApplicationException extends RuntimeException {


}


构造方法选择无参和单参的
——————————————————————————————————






重点复习:


java基础
数据库基础,查询,左右连接,子查询等等
框架,主要是spring


——————————————————————————————————————————————
day06


回顾:
1.spring容器
1)管理对象
2)启动容器(ApplicationContext ac = ClassPathXml...
3)创建对象(无参构造器(调用getBean)/静态工厂/实例工厂
4)作用域: 
scope=singleton
scope=prototype
5)生命周期
初始化
销毁方法-作用域只能是单例,使用AbstractApplicationContext
6)延迟加载
2.IOC控制反转:
1)什么是控制反转?--对象之间的依赖关系由容器来建立,如a调用b
2)什么是DI?--依赖注入
容器可以通过set或者构造器来建立
对象之间的依赖关系
3)两种方式:
set方法:
1.该类有set方法
2.<property name="b" ref="b1"/>
构造器方法:
1.该类有构造方法
2<construct-arg index="0"  ref="b1"/>
4)自动装配(了解)
autowire="byName"/ "byType"找到多个则出错/ "constructor"
5)注入基本类型的值
<property name="age" value="22"/>
6)注入集合类型的值
第一种方式:
<list> <set> <map> <props>
第二种方式
<util:list id="interestBean">
<property name="" ref="interestBean"/>


7)读取properties文件的内容
<util:properties id="" location="classpath:db.properties"/>
8)spring表达式
#{vb1.name) //vb1的类里面一定要有getName方法
#{vb1.interest[0]}
#{vb1.score['english']}


2.注解
1)组件扫描?
@Component @Service @Repository @Controller
step1:
<context:component-scan base-package="com"/>
step2:
@Component @Service @Repository @Controller
2)
@Scope("prototype")
@Lazy(true)
@PostConstruct
@PreDestroy
@Value
3)
@Autowired @Qualifier //可放到set方法里面,@Qualifier指定beanid,也可以放在
@Resource(name="beanid")




——————————————————————————————————————


springmvc
1)what?
mvc框架,用来简化基于mvc架构的web应用程序开发
2)原理:五大组件
DispatcherServlet (前端控制器)


接受请求,依据HandlerMapping的配置调用相应的 模型来处理。


HandlerMapping


包含了请求路径与模型的对应关系。


Controller (处理器)


负责处理业务逻辑。


ModelAndView


封装了处理结果。
注:处理结果除了数据之外,还可能有视图名。


ViewResolver (视图解析器)


DispatcherServlet依据ViewResolver的解析, 调用真正的视图对象来生成相应的页面。

3)编程步骤
4)读取请求参数值
request
@RequestParam
封装成javabean
5)向页面传值
request
ModelAndView
ModelMap
Session
6)重定向,默认是转发
如果返回值是字符串: "redirect:toIndex.do"
如果返回值是ModelAndView:RedirectView ModelAndView

系统分层(了解)
1)如何分层:
表示层 界面(用户交互)请求分发
业务层 业务逻辑的处理
持久层 数据库访问
上一层通过接口来调用下一层提供的服务,这样一来,下一层发生改变,不影响上一层


维护性
证券公司 CTS(集中交易系统)
业务复杂,经常变 2周一小变,一月一大变


一个大型系统好不好,就看维护性和扩展性




————————————————————————————————————————
1.处理表单的编码问题


request.setCharsetEncoding("utf-8")  //指针对post请求有效。get的话则在tomcat的server.xml设置
在实际开发中,不可能每一个请求都写一次
过滤器:过滤器先执行,然后才是servlet,而且共享同一个请求和对象
spring已经写好了过滤器,在web.xml配置


使用springmvc提供的一个过滤器
(CharacterEncodingFilter)来解决


注意:
a--表单提交方式必须为post。
b--过滤器的编码与表单提交时采用的编码一致


2.拦截器!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
登录的session验证,用spring的拦截器解决session验证的问题
如果有拦截器,前端控制器会先调用,再调用控制器
拦截器属于spring?过滤器是servlet的?
1)什么是拦截器
spring提供的一个特殊的组件,前端控制器(DispatcherServlet)在收到请求之后,会先调用拦截器,
再调用处理器(Controller)
注意:
过滤器属于servlet规范当中定义的特殊的组件
而拦截器属于spring框架
2)如何写一个拦截器
step1.。写一个java类,实现HandlerInterceptor接口
step2. 在接口方法,实现具体的拦截处理逻辑

boolean preHandle()
postHandle()
afterCompletion()
step3.配置拦截器(属于spring,因此在spring中配置)


拦截器的使用,在spring-mvc.xml一样
多个拦截器则看web.xml中的顺序
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="拦截路径"/>
<mvc:exclude-mapping path="排除不拦截的路径"/>
<bean class="拦截器类所在的包名以及类名"/>
</mvc:interceptor>
</mvc:interceptors>




——————————————
@RequestMapping("/hello.do")
public String hello(){
对于hello.do会执行拦截,但是,


就算用<mvc:mapping path="/*"/> 试图拦截所有,但是对于/demo/hello.do并不会被拦截
@RequestMapping("/demo/hello.do")




解:要想拦截所有请求,需要再加*,因为/*是对单层请求,/**是对多层请求


正解:<mvc:mapping path="/**"/>


session验证:




————————————————————————————————
过滤器和拦截器的区别:
过滤器适用性更强,跟框架没关系,更通用




3.让spring框架处理异常(将异常抛给spring框架,让spring来处理)
1)配置简单异常处理器
step1:在spring配置文件当中,


<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.NumberFormatException">error</prop>
</props>
</property>
</bean>


其中:<prop key="异常类型,如:java.lang.NumberFormatException">视图页面,如error对应的error.jsp</prop>




step2;添加异常处理页面


String str = "abcd";
str.indexOf(10); //不会报错,查询,找不到就返回-1
str.charAt(10);//报错,下标越界
2)使用@ExceptionHandler注解
step1:在处理器类中,添加一个异常处理方法
tep2;添加异常处理页面
————————————————————————————————————————
day07:
回顾:
拦截器:what?
Dispatcherervlet--》 拦截器 --》Controller
how?
step1: HandlerInterceptor接口
step2: preHandle postHandle afterCompletion






处理器Controller如果出错,则postHandle不会执行了,但是afterCompletion依旧会执行




如何配置?
使用mvc:interceptors,指定bean是哪个包哪个类。映射路径以及排除路径


______________________________________________


表单中文参数值:
<%@page contentType="text/html; charset=utf-8" %>
只要是指令,不管是taglib还算page,都会影响servlet的生成


jsp--->Servlet
response.setContentType("");
发送content-type消息头给浏览器


在spring中,配置过滤器解决中文乱码 CharacterEncodingFilter
request.setCharacterEncoding
必须是post


-------------------------------------------


异常的处理:


将异常抛给spring框架(DispatcherServlet)
方式1 :配置简单异常处理器
SimpleMappingExceptionResolver
方式2:@ExceptionHandler
step1 添加一个异常处理方法
step2 添加异常处理页面




spring-mvc总结回顾
1.spring-mvc是什么?
表示层 界面 请求分发
2.五大组件,以及相互关系(请求发给D,D依据H调用C,C将结果封装成M,C再依据V返回对象)
3.编程步骤
step1




————————————————————————————————————————————
1.springjdbc
1)什么是springjdbc?
spring对jdbc的封装
2)如何使用?
step1:导包
spring-jdbc
仅作演示,非完整应用则在new maven只需jar即可,war则需知道tomcat以及web.xml。
org.springframework spring-jdbc3.2.8


step2:添加spring配置文件
step3:配置JdbcTemplate
step4:调用JdbcTemplate提供的方法来访问数据库




——————————————————————
create table emp_warren(
id number(8) primary key,
name varchar2(50),
age number(3)


);
create sequence emp_seq_warren;


JdbcTemplate的query返回的是一个集合,查询所有或多个的时候适用
JdbcTemplate的queryForObject返回的是一个对象,查询单个的时候适用


JdbcTemplate的update():增删改




过滤器:是一个规范
________________________________________________________________________________________


MyBatis最早有apache写的  iBatis-->Google-->MyBatis--->github


oracle最大支持1024个字段




hibernate




1)MyBatis是什么?
是一个持久层框架,对jdbc做了封装,底层是jdbc
联想:springmvc是表示层框架


2)如何使用MyBatis?
step1:导包 org.mybatis mybatis 3.2.8
com.oracle ojdbc14 10.2.0.4.0
junit 4.12
step2:添加mybatis的配置文件
step3:写实体类
注意:实体类的属性名要与表的字段名一致(大小写不区分)
step4:写映射文件(以后大部分开发都是写映射文件,怎样完成数据库的记录等)**
step5:在配置文件中,指定映射文件的位置
step6:使用mybatis提供的api来访问数据库








——————————————————
oracle.jdbc.OracleDriver
oracle.jdbc.Driver.OracleDriver也能用


只要是java类都最好实现序列化接口,不仅仅是实体类


同一个id在映射文件中不能一样
<insert id="" parameterType="entity.Emp"> id要求唯一
注意:<insert></insert>标签内的sql语句不能加分号,#{name}#不能有空格




————————————————————————————————————————————
day 08
Mybatis


查询方法,映射文件不是用<insert>标签,而是<select>,类型是resultType


<select id="findAll" resultType="entity.Emp">返回的是一个集合,因此
在测试方法中获取结果需要用集合接收。因为是查询,因此不需要提交事务session.commit(),但是
还是需要close(),毕竟是资源,资源使用完毕都要释放


查询单个实例:
<T> T selectOne(String statement ,Object parameter) 
查询所有:
<E> List<E> selectList(String statement, Object parameter)
3)mybatis的原理:
SqlSessionFactory创建很多statement对象,其实质是一个Map集合


Map的key是sqlId
value就是statement对象
SqlSessionFactory创建SqlSession
调用SqlSession是传参(sqlId,参数)。如插入操作,参数是emp实例,包含了emp的信息
有了sqlId,依据sqlId从Map中找到对应的statement并执行




——————————————————————————————————————


查询单个实例:
<T> T selectOne(String statement ,Object parameter) 
findById


<!-- parameterType="java.lang.Integer" -->
<select id="findById" parameterType="int" resultType="entity.Emp">
SELECT * FROM emp_warren WHERE id=#{id1}
</select>




#{id1}的值并不是来自某个对象的某个属性,所以可以任意名字,id或者id1都可以




@Test
public void testfindById(){
Emp e = session.selectOne("test.findById",1);

System.out.println(e);


}

mybatis查询不到数据会返回null,而jdbc是报异常


练习:
建一张表dept
create table dept_warren(
id number(8) primary key,
deptno varchar2(50),
loc varchar2(100)
);
create sequence dept_seq_warren;






____________________________________________________________________




有几条记录,就有几个map对象。
1.mybatis会将查询到的一条记录转换成一个map对象(一条记录对应一个map)
2.再将map中的数据存放到实体对象
 
emp :id name age
1 Sally22


map : key id 1
key name Sally
key age 22


________________________________________


4)返回Map类型的结果
mybatis会将查询到的记录先转换成对应Map对象(以字段名作为key,以字段值作为value,
一条记录对应一个map


map获取返回的是大写,因为oracle默认转成大写
应用范围:当数据库表很大,有很多字段,如几十上百个,但是只需要获取其中的几个字段,就不需要使用
实体类了,而是用Map返回
————————————————————————————————————————————


实体类一般不要更改,有可能其他地方正在使用。


5)解决实体类的属性和数据库的字段不一致


方式一:使用别名
select empNo,ename,age ...
方式二:使用resultMap



<!-- 测试Emp2.java的属性名和数据库字段名不同。
使用了resultMap那么这里的resultType就不用了,改成resultMap对应 -->
<select id="findById3" parameterType="int" resultMap="emp2Map">
SELECT * FROM emp_warren WHERE id=#{id1}
</select>
<!-- id要求唯一,type:实体类的名字 
resultMap:负责告诉mybatis如何将字段名与实体类的属性名进行对应
如果实体类和数据库的字段名不一致,mybatis会看resultMap
-->
<resultMap type="entity.Emp2" id="emp2Map">
<result property="empNo" column="id"/>
<result property="ename" column="name"/>
</resultMap>


————————————————————————————————————————————




6)Mapper映射器(该功能为Google改进的ibatis)


Mapper映射器是什么?
是符合映射文件的接口
(2)Mapper映射器的要求:
接口要求如下:
a。方法名要与sql的id一致。如叫做save也一样叫做save方法,大小写必须一样
b。方法的参数类型要与parameterType一致
c。方法的返回类型要与resultType一致






映射文件要求:命名空间namespace必须等于接口名(包含包名)


————————————————————————————————————
写了接口则mybatis自动提供一个实现接口的对象,不用写DAO的实现类了
一个线程一个stack
————————————————————————————————————————
(3)编程步骤
step1. 写一个映射器(即一个接口)。
step2. 调用SqlSession提供的getMapper方法。
注:该方法会返回一个符合映射器要求的对象






获取只需要调用接口的方法即可
EmpDAO dao = session.getMapper(EmpDAO.class); 

List<Emp> emps = dao.findAll()
————————————————————————————————————————
spring集成mybatis


step1. 导包。
spring-webmvc3.2.8
mybatis3.2.8
mybatis-spring1.2.3
spring-jdbc3.2.8
dbcp1.4
ojdbc10.2.0.4.0
junit4.12


step2.配置文件
注意:只需要添加spring的配置文件,在该文件中,配置一个SqlSessionFactoryBean
SqlSessionFactoryBean包含了连接池和映射文件的信息
step3. 实体类 
step4. 映射文件 
step5. Mapper映射器 
step6. 在spring的配置文件当中,添加 MapperScannerConfigurer。
该bean负责调用SqlSession的getMapper方法, 创建符合Mapper映射器要求的对象。


注:
该bean会将这个对象添加到spring容器里面
(默认id是首字母小写之后的接口名,也可以使用@Repository重命名,(可回忆前面讲的注解),
而且,
在配置文件中,不需要另外再加上注解扫描了,因为MapperScannerconfigure自己会扫描)。




step7.启动spring容器,调用getBean方法
————————————————————————————————————————


<!-- 配置SqlSessionFactoryBean -->
<bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定连接池的位置 -->
<property name="dataSource" ref="ds"/>
<!-- 指定映射文件的位置 -->
<property name="mapperLocations" value="classpath:entity/*.xml"/>
</bean>


<!-- 配置MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定Mapper映射器所在的包 -->
<property name="basePackage" value="dao"></property>
</bean>




mapperLocations注意不要少了s






————————————————————————




sqlSessionFactory属性可以不用指定,会以Autowired方式自动注入


缺省值:映射器的首字母小写
如EmpDAO接口,则getBean("empDAO),当然也可以使用前面学的注解修改为指定的名字,@Repository()
















晨曲
晨旭
晨映




——————————————————————————————————————


回顾:mybatis:持久层的框架,底层是jdbc,只不过做了封装


mybatis
mybatis-spring。


可能有些DAO接口不使用mybatis实现,而是用其他的。对于某些特定的查询,要求查询快,比如jdbc就比mybatis快


讲究开发效率:mybatis
要求查询高效:jdbc
当多种持久层技术共存时,如何解决?
——给MapperScannerConfigurer加个属性,叫annotationClass
其属性值就是一个注解value="org.tarena.annotation.MyBatisRepository"


哪个要被扫描就注解MyBatisRepository
需要自己写该注解






2)只扫描特定的Mapper映射器
step1.自定义一个注解。src/main/java右键new一个annotation
起个标识作用,就像之前学的Serializable接口一样


step2.将该注解添加到要扫描的映射器文件。加在映射器文件前面,EmpDAO接口
@Repository("empDAO")
@MyBatisRepository
public interface EmpDAO {...
step3.配置MapperScannerConfigurer的属性annotationClass


——————————————————————————————————————————
3)spring集成mybatis的另外一种方式(了解)
SqlSessionTemplate


SqlSessiontemplate利用sqlsessionfactorybean获取sqlsession




step1. 导包。
step2. 添加spring的配置文件。
注:删除MapperScannerConfigurer的配置。
step3. 实体类。
step4. 映射文件。
step5. DAO接口。
step6. DAO实现类。
注:注入SqlSessionTemplate,调用该对象的方法。
step7.配置SqlSessionTemplate。










Spring+Mybatis
系统分层
表示层 springmvc
业务层 spring
持久层 mybatis


毕业前5天讲:
SSH 
表示层 Struts2 
业务层 Spring
持久层 Hibernate


练习:
使用spring+mybatis完成NETCTOSS的登录


step1.导包
mybatis包,mybatis-spring包
step2.在spring的配置文件中,添加:
SqlSessionFactoryBean。
MapperScannerConfigurer
step3.解决实体类和数据库实例名不一致的情况,用别名或者resultMap
step4.映射文件
step5.映射器。
step6.测试AdminDAO






注意:


在spring配置文件中,如果配置了MapperScannerConfigurer,而且还保留了之前的组件扫描和注解扫描,则在
测试AdminDAO持久层的时候会报出CostDAO冲突。这时候删除之前的组件扫描和注解扫描可正常运行


<!-- 配置组件扫描 -->
<context:component-scan base-package="com.tarena.netctoss"/>
<!-- 配置mvc注解扫描 -->
<mvc:annotation-driven/> 




但是需要注意


<!-- 配置MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定Mapper映射器所在的包 -->
<property name="basePackage" value="com.tarena.netctoss.dao"/>  
<!-- 指定只有带该注解的映射器才会被扫描 -->

</bean>


正确写法:
路径要classpath,用/
property name="mapperLocations" value="classpath:com/tarena/netctoss/entity/*.xml"/>
包才是.
<property name="basePackage" value="com.tarena.netctoss.dao"/>  














这里MapperScannerConfigurer的扫描路径是com/tarena/netctoss/dao
而之前的组件扫描是com.tarena.netctoss,
测试其他子包的类时注意,比如此时包controller内的注解便已经失效


总结:原有的组件扫描和mvc注解扫描是不能删除的,而把
MapperScannerConfigurer的扫描路径改为上一级com/tarena/netctoss
明显不能解决问题,这时候的状态就是多种DAO技术共存的局面,jdbc和mybatis,
因此需要特定扫描,既能用MapperScannerConfigurer,也不影响原有的组件扫描和mvc注解扫描
所以,加个属性:
<!-- 指定只有带该注解的映射器才会被扫描 -->
<property name="annotationClass"  value="com.tarena.netctoss.annotations.MybatisRepository"></property>
</bean>






SqlSessionTemplate实际较少用,属于mybatis早期的技术,比较麻烦,需自己写DAO的实现类


——————————————————————————————————————————————


复制项目必须要修改pom的<artifactId>spring-netctoss_v2</artifactId>,否则无法启动服务器


路径要classpath,用/
property name="mapperLocations" value="classpath:com/tarena/netctoss/entity/*.xml"/>
包才是.
<property name="basePackage" value="com.tarena.netctoss.dao"/>  




理解:netcotss之所以不写annotationClass属性也能正常运行,是因为其dao包里面只有一个AdminDAO
,而如果加上CostDAO,一样提示冲突!!!!!!!




————————————————————————————————————————————————————


AJAX:
是一种用来改善用户体验的技术,其本质是利用浏览器 提供的一个特殊的对象(XMLHttpRequest,也可称之为 ajax对象)向服务器发送异步请求。服务器返回部分数据 (通常不需要返回完整页面),浏览器利用这些数据对当前 页面做部分更新。整个过程,页面无刷新,不打断用户的操作




asynchronous javascript and xml
改善用户体验


javascript/jquery


一个ajax对象就是XMLHttpRequest




xml非常重要,明后天讲json,代替部分xml功能
特定场合如服务器返回的数据比较复杂,则用xml


原理:




2)如何获得ajax对象
javascript 有兼容性问题
ajax最早在ie5.5提供 activeXobject
firefox,chrome等效仿提供此类对象,叫XMLHttpRequest


w3c 整合


——————————————————————————————————————————————————
day10
ajax对象的几个重要属性


onreadystatechange:绑定一个事件处理函数,该函数用来处理reaystatechange事件
注:当ajax对象的readyState属性值发生了改变,比如,从0变成了1,则会产生readystatechange事件
readyState请求的状态,有5个值(0,1,2,3,4),表示ajax对象与服务器通信的进展,其中,4表示ajax对象已经获得了服务器返回的所有的数据
0:尚未初始化
1:正在发送请求
2:请求完成
3:请求成功,正在接受数据
4:数据接收成功
responseText:获得服务器返回的文本数据
responseXML:获得服务器返回的xml数据
status:获得状态码,如200就是正常


获得服务器返回的数据if(readState==4)  //js


4)编程步骤
step1.获得ajax对象
比如 var xhr = getXhr();
step2.发送请求
方式一:get请求
xhr.open('get','check_uname.do?name=sally&age=22',true); //true:表示异步请求,如果是
false则表示同步请求(当ajax对象发送请求时,浏览器会锁定当前页面,用户不能够对当前页面做任何操作)
xhr.onreadystatechange=f1;
xhr.send(null);


方式二:post请求
xhr.open('post','check_uname.do');
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
xhr.onreadystatechange=f1;
xhr.send('uname=Sally');


按照http协议的要求,如果发送的请求是post,要求携带content-type消息头
(浏览器提交表单自动添加了消息头),非表单提交都不加消息头,所以需要调用Request
Header方法来添加
















step3.编写服务器端的程序。通过只需要返回部分数据(不再需奥返回完整的页面
step4.写事件处理函数
function f1(){
if(xhr.readState==4 && xhr.state==200){
//获得服务器返回的数据
var text = xhr.responseText;
}

}








————————————————————————————————————————————
5)缓存问题:
什么是缓存问题?
当使用ie浏览器时,ajax对象如果发送的是get的请求,
会检查请求地址是否访问过,如果访问过,则不再发送新的请求,而且显示之前访问过的结果
(也就是说,第一次访问请求时,会将结果缓存下来)


如何解决?
在请求地址后面加上随机数








!!!!!!!!!!!!!!!!
if(xhr.readState==4 && xhr.status==200){  //又是少写了个y
注意ready的拼写








6)中文乱码:


虽然tomcat的server.xml配置了 URIEncoding="utf-8",但是用ie浏览器用get请求发送,也还是乱码,虽然非ie已经正常


因为ie浏览器默认使用gbk对中文进行编码,其他非ie浏览器默认
会使用utf-8对中文进行编码。
而服务器默认会使用iso-8859-1对中文进行编码


所以 URIEncoding="utf-8" 不能保证所有的浏览器编码正常
解决方式:
step1.服务器端统一使用utf-8来解码。比如 URIEncoding="utf-8"
step2.在客户端,使用encodeURI函数对中文数据进行编码
注:encodeURI是javascript内置的函数。




发送post请求
产生乱码的原有:
浏览器默认会使用utf-8对中文进行编码,服务器使用iso-8859-1来解码


解决方式:


req.setCharacterEncoding("utf-8");




练习:级联下拉列表




————————————————————————————————————————————


day11
回顾:
ajax
what?
how?
step1:获得ajax对象
step2 发请求
get

post
step3. 编写服务器端的程序。通过只需要返回部分 数据(不再需要返回完整的页面)。
step4. 写事件处理函数。




缓存问题:当用ie且使用get请求时。
解决:1.在请求地址后面添加一个随机数。
2.使用post发送


——————————————————————————————————————————
1.JSON(javascript object notation)js对象声明
1)什么是JSON
是一种轻量级的数据交换格式
直接读取xml会比较慢,json解析更简单更快
借鉴了js中的一种创建对象的语法
数据交换:将数据先转换成一种与平台无关的数据格式(比如转换成xml),然后发送给接收方来处理


轻量级:与xml相比,JSON文档要小,解析的速度更快


2)JSON语法:
表示一个对象
{属性名:属性值,属性名:属性值,属性名:属性值}
注:属性名必须使用双括号括起来
属性值可以是String,number,true/false,null,Object
3)属性值如果是字符串,也必须使用双引号括起来


js中:
{"name":"sally","age":22}
{name:"sally",age:22}
{'name':'sally','age':22}




表示一个对象组成的数组
[{},{},{} ]






java对象如何转换成json对象?
json-lib
JSONObject/JSONArray
jackson
fastjson


javascript两个内置对象:Math/Object


新加入:JSON.parse(str)


————————————————————————————————————


Stock s = new Stock();
//使用json官方提供的工具(json-lib)来转换
JSONObject jsonObj = JSONObject.fromObject(s);
String jsonStr = jsonObj.toString();


——————————————————————————————
List<Stock> stocks = new ArrayList<Stock> ();
/*
 * fromObject方法可以传入数组或者List集合
 */
JSONArray jsonArr = JSONArray.fromObject(stocks);


String jsonStr = jsonArr.toString();




——————————————————————————————————————————




### 将json字符串转换成javascript对象
javascript内置的


$(function(){})整个页面加载完成之后执行




$.ajax({
"url":"quoto.do",
"type":"post",
"data":"size=3&id=4",  //参数名(服务器getParameter获取的):size,值:3
也可以这样:  "data":{"size":"3","id","4"}


"dataType":"json",
"success":function(这里传参数,即服务器返回的数据,如果是字符串,会自动转成js对象,如果是数组则转成js数组){}  //相当于自己写的ontreadystatechange
});








对于jquery, $.ajax方法会自动将json字符串转换成js对象




#jQuery对ajax的支持
## $.ajax方法
用法:
$.ajax({});
常见的选项参数有这样的一些:
url:请求地址
type:请求类型(比如:get)
data:请求参数有两种格式:
第一种:请求的字符串形式,比如size=3
第二种:对象形式,比如{"size":3}
dataType:服务器返回的数据类型(text,json)
text:文本
json:json字符串
xml:xml文档(比较复杂的数据)


success:当服务器处理正确,用来处理服务器返回的数据的函数


error:当服务器出错,用来处理的函数






业务分离:
html:数据
jquery:行为
css:样式


jquery的显示:
$("span").html(num);
$("input.button").value(num);
js的显示:
obj.innerHTML=num;
obj.value=num;




如果server发送的不是Object或者数组,而是Sring或者基本数据类型,不需要写JSONObject
那么,
将$.ajax的dataType设置为text即可,而不是用json,


————————————————————————————————————————




## load方法:


服务器返回的数据不需要处理,直接追加到节点上,适用于随机数案例


用法:
$obj.load(url);


作用:向服务器发送异步请求,将服务器返回的数据直接添加到符合要求的节点之上


function f2(){
/*
*向服务器发送异步请求(请求地址是getNum.do),然后将服务器返回的数据
*直接添加到#d1对应的节点相当于给该节点innerHTML赋值
*/
$("#d3").load('getNum.do');
}


练习:
检查用户名注册,用jquery写































































































































0 0
原创粉丝点击