目录
📢:哈喽~☀️欢迎加入程序🐒大家庭,快点开始✒️自己的黑客帝国吧 ~🌊🌊
内容简述:Spring简介、Spring容器、Spring IOC/DI、Spring 五大组件、Spring MVC、Spring JDBC、MyBatis、AJAX。
一、Spring简介、Spring容器
1. Spring是什么?
- 开源的,用来简化企业级应用开发的应用开发框架。
(1)简化开发
- Spring对常用的api(比如jdbc) 做了封装,这样,可以大大简化这些api的使用。(比如使用springjdbc访问数据库,就不用考虑如何获取连接和关闭连接了)。
(2)解耦
- Spring帮我们建立对象之间的依赖关系,这样,对象之间的耦合度会大大降低,代码的维护性会大大提高。(代码要求:高内聚(类的功能要单一),低耦合。)
(3)集成其它框架
-
Spring可以将其它的一些框架集成进来(比如用于定时任务处理的Quartz框架等),方便这些框架的使用。
(因为spring可以集成其他框架,所以spring又叫做一站式框架)
2.Spring容器
(1)什么是Spring容器?
- Spring框架中的一个核心模块,用于管理对象。
(2)启动Spring容器
-
step1.导包。
spring-webmvc(org.springframework),junit
-
step2. 添加spring配置文件。
-
step3. 启动容器。
String config = "applicationcontext.xml";
/*
* ApplicationContext 是接口
* ClassPathXmlApplicationContext 是一个实现类,该类会依据类路径去查找spring配置文件,然后启动容器。
*/
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
(3)创建对象
-
1)方式一: 无参构造器
-
step1. 为类添加无参构造器(或者缺省构造器)
-
step2. 在配置文件里面,添加bean元素。(注意:与javabean无关)
注:bean就是容器所创建的对象。
-
step3. 启动容器,调用容器的getBean方法。
-
<!-- 使用无参构造器创建对象 -->
<!--
id: bean的名字,要求唯一。
class: 完整的类名(包括包名)
-->
<bean id="stu1" class="first.Student"/>
- 2)方式二: 静态工厂方法 (了解)
<!-- 使用静态工厂方法创建对象 -->
<!--
factory-method: 指定一个静态方法。
容器会调用该类的静态方法来创建一个对象。
-->
<bean id="cal1" class="java.util.Calendar" factory-method="getInstance"/>
- 3)方式三: 实例工厂方法(了解)
<!-- 使用实例工厂方法创建对象 -->
<!--
factory-bean: 指定一个bean的id,容器会调用该bean的示例方法来创建一个对象。
-->
<bean id="time1" factory-bean="cal1" factory-method="getTime" />
(4)作用域
-
1)默认情况下,容器对于每个bean元素,只会创建一个实例。
-
2)如果将作用域设置为"prototype",则每调用一次getBean方法,就会创建一个新的实例。
<!-- 指定作用域 -->
<!--
scope: 用来指定作用域,缺省值是singleton(单例,即只会创建一个对象),
如果值是prototype(每调用一次getBean方法创建一个新的对象)。
lazy-init: 如果值为true,标识延迟加载。
-->
<bean id="t1" class="basic.Teacher" scope="singleton" lazy-init="true" />
(5)延迟加载 (了解)
-
1)默认情况下,容器启动之后,会将作用域为"singleton"的bean创建好。
-
2)延迟加载指的是,容器启动之后,对作用域为"singleton"的bean不再创建,直到调用了getBean方法才会创建。
(6)生命周期
- 1)初始化方法
- 容器创建好bean的实例之后,会立即调用初始化方法。
- 2)销毁方法
- 容器关闭之前,会调用销毁方法。
<!-- 指定初始化方法和销毁方法 -->
<!--
init-method: 指定初始化方法名。
destroy-method: 指定销毁方法名。
注意:销毁方法只对作用域为singleton的bean有效。
-->
<bean id="ms1" class="basic.MessageService" init-method="init" destroy-method="destroy"/>
二、Spring IOC、参数值注入
1. IOC/DI
(1)IOC(Inversion Of Controll 控制反转)
- 对象之间的依赖关系由容器来建立。
(2)DI(Dependency Injection 依赖注入
- 容器可以通过调用set方法或者构造器来建立对象之间的依赖关系。
总结: IOC是目标,DI是手段。
(3)依赖注入的两种方式
- 1)方式一: set方法注入
- step1. 添加set方法;
- step2. 在配置文件中,使用<property>元素来配置。
<bean id="b1" class="ioc.B"/>
<!--
property: 让容器调用set方法来建立依赖关系。
其中,name属性指定属性名,ref指定被注入的bean的id。
-->
<bean id="a1" class="ioc.A">
<!-- b为属性名,spring会调用将属性名首字母大写,前面添加set的方法,比如setB()-->
<property name="b" ref="b1" />
</bean>
- 2)方式二: 构造器注入
- step1. 添加构造器;
- step2. 在配置文件当中,使用<constructor-arg>元素来配置。
<!-- 构造器注入 -->
<!--
constructor-arg: 容器会采用构造器来建立依赖关系。其中,index指定参数的下标。
-->
<bean id="cp1" class="ioc.Computer" />
<bean id="mg1" class="ioc.Manager">
<constructor-arg index="0" ref="cp1"/>
</bean>
(4)自动装配
-
自动装配,指的是容器依据某些规则,自动建立对象之间的依赖关系。
(底层仍然是需要调用set方法或者构造器)
-
1)默认情况下,容器不会自动装配。
-
2)设置autowire属性
-
autowire: 表示让容器自动建立对象之间的依赖关系。
-
byName: 依据属性名查找对应的bean(就是以属性名作为bean的id来查找),找到之后,调用set方法来建立依赖关系。
注:如果找不到,则不注入。
-
byType: 依据属性类型来查找对应的bean,找到之后,调用set方法来建立依赖关系。
注:如果找到多个,则会出错。
-
constructor: 与byType类似,只不过,调用构造器来注入。
-
(5)注入基本类型的值
- 使用value属性来注入,spring容器会帮我们做一些类型的转换工作,比如将字符串转换成数字。
(6)注入集合类型的值 (List,Set,Map,Properties)
-
方式一: 直接注入
注:list的value值可以重复,set的value值不可以重复(重复的话只存一遍)。
xml代码
<list>
<value>台球</value>
<value>钓鱼</value>
<value>看电视</value>
<value>看电视</value>
</list>
<set>
<value>北京</value>
<value>上海</value>
<value>武汉</value>
<value>武汉</value>
</set>
<map>
<entry key="english" value="70"/>
<entry key="math" value="90"/>
</map>
<props>
<prop key="username">Sally</prop>
<prop key="password">1234</prop>
</props>
java代码
public class ValueBean {
private String name;
private int age;
private List<String> interest;
private Set<String> city;
private Map<String, Double> score;
private Properties db;
getXXX(){};
setXXX(){};
toString(){};
}
注意:Properties是键值对,值只能是字符串
- 方式二: 引用的方式注入
- step1. 将集合类型的值先配置成一个bean。
- step2. 再将这个bean注入到对应的bean里面。
<util:list id="interestBean">
<value>喝酒</value>
<value>烫头</value>
<value>抽烟</value>
</util:list>
<!-- 采用引用的方式注入集合类型的值 -->
<bean id="eb1" class="value.ExampleBean">
<property name="interest" ref="interestBean"/>
</bean>
注意:util是命名空间,namespace,是为了区分同名的元素而添加的限定
(7)读取.properties文件的内容
<!-- 读取.properties文件的内容 -->
<!--
location: 指定属性文件的位置。
注:classpath,表示让容器依据类路径去查找属性文件。
容器回读取指定位置的文件的内容,并且将这些内容存放到Properties对象里面。
-->
文件位置:
文件内容:
测试:
@Test
// 测试 读取属性文件的内容
public void test8(){
String config = "value.xml";
AbstractApplicationContext ac = new ClassPathXmlApplicationContext(config);
Properties props = ac.getBean("config", Properties.class);
System.out.println(props);
ac.close();
}
结果:
三、基于注解的组件扫描、SpringMVC、五大组件
注意:javaBean和bean一点关系都没有。
(8)spring表达式
- 读取bean的属性
1.使用注解来简化配置文件
(1)什么是组件扫描?
- 容器会扫描指定的包及其子包下面的所有的类,如果该类前面有特定的注解比如@Component),则容器会将其纳入容器进行管理(相当于在配置文件里面有一个bean元素)。
(2)如何进行组件扫描?
-
step1. 在类前面添加特定的注解,比如 @Component
(注:默认的id是首字母小写之后的类名。)
- step2. 在配置文件当中,配置组件扫描。
(3)依赖注入相关的注解
-
1)@Autowired @Qualifier–(依赖于spring,@Autowired先根据类型查找(byType,byType默认使用set方法注入),如果找到一个接口下面有多个实现,则再根据名称查找(byName,或者直接使用@Qualifier实现byName方式),如果还找不到就会抛出异常)
(注:该注解支持set方法和构造器注入。)
注意:@Autowired不需要手动显式地声明set方法和构造器方法。
注意:
- bean配置文件中的set注入和构造器注入指的是将容器中创建好的bean实例通过set方法和构造器方法注入到相应的属性中;
- @Autowired,@Resource注解是将容器中创建好的bean实例直接注入到相应的变量中,然后调用修饰的方法给类的属性赋值。其中,@Autowired支持修饰set方法和构造器方法,@Resource只支持修饰set方法。
-
2)@Resource–(依赖于javaee,包为javax.annotation-api-1.2.jar)
(设定项目tomcat依赖的时候会自动导入)
(注:该注解只支持set方法注入。)
(4)注入基本类型的值和spring表达式的值
SpringMVC
(1)什么是SpringMVC?
-
用来简化基于MVC架构的web应用程序开发的框架。
(注:SpringMVC是spring中的一个模块。)
(2)五大组件
-
1)有哪五大组件?
- DispatcherServlet 前端控制器(在web.xml文件中配置)
- HandlerMapping 映射处理器(在Spring配置文件中配置)
- Controller 处理器(在Spring配置文件中配置+代码实现)
- ModelAndView 处理结果和视图名(在Spring配置文件中配置)
- ViewResolver 视图解析器
-
2)它们之间的关系
-
a.请求发送给DispatcherServlet来处理,DispatcherServlet会依据HandlerMapping的配置调用对应的Controller来处理。
-
b.Controller将处理结果封装成ModelAndView对象,然后返回给DispatcherServlet。
-
c.DispatcherServlet会依据ViewResolver的解析调用对应的视图对象(比如jsp)来生成相应的页面。
(注:视图部分可以使用jsp,也可以使用其它的视图技术,比如 freemarker,velocity 等等。)
-
(3)编程步骤
- step1. 导包 spring-webmvc
- step2. 添加配置文件。
- step3. 配置DispatcherServlet。
- step4. 写Controller。
- step5. 写jsp。
- step6.在配置文件当中,添加HandlerMapping, ViewResolver的配置。
<!-- 配置HandlerMapping映射处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello.do">helloController</prop>
</props>
</property>
</bean>
<!-- 配置Controller处理器 -->
<bean id="helloController" class="controller.HelloController" />
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" /><!-- 前缀 -->
<property name="suffix" value=".jsp" /><!-- 后缀 -->
</bean>
练习: http://localhost:8080/springmvc-lab/toLogin.do 返回一登录页面。
四、SpringMVC应用
1. 基于注解的SpringMVC应用
(1)编程步骤
- step1.导包 spring-webmvc
- step2.添加spring配置文件。
- step3.配置DispatcherServlet。
- step4.写Controller
- 1.不用实现Controller接口;
- 2.方法签名不做要求,返回值可以是ModelAndView,也可以是String;
- 3.可以添加多个方法;
- 4.使用@Controller;
- 5.可以在方法前或者类前添加@RequestMapping,相当于HandlerMapping。
- step5.写jsp
- step6.在配置文件当中,添加ViewResolver配置,添加组件扫描,添加MVC注解扫描。
<!-- 配置组件扫描 -->
<context:component-scan base-package="controller"/>
<!-- 配置MVC注解扫描 -->
<mvc:annotation-driven />
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" /><!-- 前缀 -->
<property name="suffix" value=".jsp" /><!-- 后缀 -->
</bean>
注意:需要添加相应的注解,比如@RequestMapping,MVC注解扫描才会扫描到。
(2)读取请求参数值
- 1)方式一:通过request提供的方法
public String login(HttpServletRequest request){
System.out.println("login()");
String adminCode = request.getParameter("adminCode");
}
- 2)方式二:通过@RequestParam注解
public String login2(String adminCode, @RequestParam("pwd")String password){
// 当请求的参数和实际的参数名不一致的时候,使用@RequestParam注解
}
-
3)方式三:通过javabean
-
step1. 先写一个java类
/** * 用于封装请求参数值,属性名与请求参数名一致 * 注: * 名称要一样,类型要匹配 * (数字会自动进行相应的类型转换,比如将String转换成int) * 提供相应的get/set方法 * @author ACGkaka */ public class AdminParam { private String adminCode; private String pwd; private int phone; public int getPhone(){ return phone; } public void setPhone(int phone){ this.phone = phone; } public String getAdminCode(){ return adminCode; } public void setAdminCode(String adminCode){ this.adminCode = adminCode; } public String getPwd(){ return pwd; } public void setPwd(String pwd){ this.pwd = pwd; } }
-
step2. 将该类作为方法参数
public String login3(AdminParam ap){ System.out.println("login3()"); System.out.println("adminCode:" + ap.getAdminCode()); return "index"; }
-
(3)向页面传值
-
1)方式一:将数据绑订到request
@RequestMapping("/login4.do") public String login4(AdminParam ap,HttpServletRequest request){ System.out.println("login4()"); String adminCode=ap.getAdminCode(); request.setAttribute("adminCode", adminCode); //默认情况下,DispatcherServlet //会使用转发。 return "index"; }
-
2)方式二:返回ModelAndView
@RequestMapping("/login5.do") public ModelAndView login5(AdminParam ap){ System.out.println("login5()"); String adminCode=ap.getAdminCode(); //step1.将数据添加到一个Map对象里面 Map<String,Object> data=new HashMap<String, Object>(); //相当于执行了request.setAttribute data.put("adminCode", adminCode); //step2.将Map对象添加到ModelAndView中 ModelAndView mav=new ModelAndView("index",data); return mav; }
-
3)方式三:将数据添加到ModelMap
@RequestMapping("/login6.do") public String login6(AdminParam ap,ModelMap mm){ System.out.println("login6()"); String adminCode=ap.getAdminCode(); mm.addAttribute("adminCode",adminCode); return "index"; }
-
4)方式四:将数据绑订到session
@RequestMapping("/login7.do") public String login7(AdminParam ap,HttpSession session){ System.out.println("login7()"); String adminCode=ap.getAdminCode(); session.setAttribute("adminCode", adminCode); return "index"; }
(4)重定向
-
1)方法的返回值是String,比如: return “redirect:toIndex.do”;
@RequestMapping("/login8.do") public String login8(){ System.out.println("login8()"); return "redirect:toIndex.do"; } @RequestMapping("/toIndex.do") public String toIndex(){ System.out.println("toIndex()"); return "index"; }
-
2)方法的返回值是ModelAndView,比如:
@RequestMapping("/login9.do") public ModelAndView login9(){ System.out.println("login9()"); RedirectView rv=new RedirectView("toIndex.do"); ModelAndView mav=new ModelAndView(rv); return mav; }
五、系统分层、登录案例
1.系统分层
(1)为什么要分层?
- 为了系统好维护,系统的设计应该要做到“高内聚,低耦合”。
- “高内聚”:指的是类的职责要单一,这样,一个类就可以会拆分成多个类(比如AccountService拆分成了AccountService和AccountDAO),这样,就形成了分层的概念。
- “低耦合”:指的是类与类之间不要直接依赖。(AccountService要调用AccountDAO,应该使用依赖注入)。
(2)如何分层?
-
表示层:数据展现和操作界面,以及请求分发。(Controller)
-
业务层:封装了业务逻辑。 (Service)
-
持久层: 封装了数据访问逻辑。(DAO)
注:表示层调用业务层,业务层调用持久层。上一层通过接口来调用下一层提供的服务(这样,下一层的实现发生了改变,不影响上一层)。
六、中文乱码处理、拦截器、Spring处理异常
1. 表单包含有中文参数值,如何读取?
- springmvc提供了一个过滤器(CharacterEncodingFilter),只需要配置该过滤器即可。
注意:
a. 表单的提交方式必须是"post"。
b. 编码与浏览器端的一致。
2.拦截器
(1)什么是拦截器?
- DispatcherServlet收到请求之后,如果有拦截器,会先调用拦截器,然后再调用Controller。
补充:过滤器属于servlet规范,而拦截器属于spring框架。
(2)如何写一个拦截器?
-
step1. 写一个java类,实现HandlerInterceptor接口。
-
step2. 在接口方法里面,实现拦截处理逻辑。
-
step3. 配置拦截器。
面试题:过滤器和拦截器在验证登录功能方面有什么区别?
- 过滤器更通用一些,拦截器是依赖于spring框架的!
面试题:过滤器和拦截器的区别?
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调
2、过滤器依赖于servlet容器,而拦截器依赖于Spring容器
3、Filter是Servlet规范固定的,只能用于Web程序中,而拦截器既可以用户Web程序,也可以用于Application、Swing程序中
4、Filter在只在Servlet启动前后起作用。而拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用弹性更大一些,所以在使用Spring架构的程序中,要优先使用拦截器。
5、过滤器和拦截器触发时机不一样,过滤器是在【请求进入容器后,但请求进入servlet之前】进行预处理的。请求结束返回也是,是【在servlet处理完后,返回给前端之前】。
6、拦截器可以获取IOC容器中的各个bean,而过滤器就不行,因为拦截器是spring提供并管理的,spring的功能可以被拦截器使用,在拦截器里注入一个service,可以调用业务逻辑。而过滤器是JavaEE标准,只需依赖servlet api ,不需要依赖spring。
详细链接:https://www.iteye.com/blog/uule-2442198
3.让spring框架帮我们处理异常
-
即:将异常抛给spring框架,让spring框架来处理。
-
默认情况下,spring框架会将异常直接抛给最终的用户。
(1)方式一:配置简单异常处理器。
- step1.在spring配置文件当中,配置简单异常处理器。
- step2.添加相应的异常处理页面。 注:简单异常处理器,不能够对异常做复杂的处理。
(2)方式二: @ExceptionHandler。
-
step1. 在处理器当中添加一个异常处理方法。该方法前面需要添加@ExceptionHandler注解。
-
step2. 在异常处理方法里面,依据异常类型做不同的处理。
/**
* 这是一个异常处理方法
* e:处理器方法所抛出的异常。
* @return
*/
@ExceptionHandler
public String handlerEx(Exception e,HttpServletRequest request){
System.out.println("handleEx()");
if(e instanceof NumberFormatException){
e.printStackTrace();
request.setAttribute("msg", "亲,请输入正确的数字");
return "error3";
}else if(e instanceof StringIndexOutOfBoundsException){
e.printStackTrace();
request.setAttribute("msg", "下标越界啦");
return "error3";
}
return "error";
}
七、SpringJDBC、Mybatis
1.SpringJdbc、Mybatis
(1)SpringJdbc是什么?
- Spring框架对jdbc的封装。
(2)编程步骤
- step1.导包 spring-webmvc,spring-jdbc,ojdbc,dbcp,junit。
- step2.添加spring配置文件。
- step3.配置JdbcTemplate。
注:JdbcTemplate把一些重复性的代码(比如获取连接,关闭 连接,异常处理等等都写好了),我们只需要调用该对象的方法就可以很方便的访问数据库。
- step4.调用JdbcTemplate的方法来访问数据库。
注:通常将JdbcTemplate注入到DAO。
@Respository("employeeDAO")
public class EmployeeDAO {
@Autowired
@Qualifier("jt")
private JdbcTemplate jt;
}
create table t_emp(
id number(8)primary key,
name varchar2(20),
age number(3)
);
create sequence t_emp_seq;
总结:
(1)Spring提供的JdbcTemplate对jdbc做了封装,大大简化了数据库的操作。
(2)Spring提供的JdbcTempate能直接数据对象映射成实体类,不再需要获取ResultSet去获取值/赋值等操作,提高开发效率。
(3)调用的还是javaweb中的jdbc,是对原生jdbc的封装,代码量更小,如同DBUtils一样。
2.MyBatis
(1)MyBatis是什么?
- 开源的持久层框架。
注:MyBatis底层仍然是jdbc。
-
Jdbc
- 优点:性能高,易掌握;
- 缺点:代码繁琐。
-
Hibernate
- 优点:不用写sql,代码简洁;
- 缺点:性能不好,复杂自动生成的sql效率低下,不容易掌握。
-
MyBatis
- 优点:代码简洁,容易掌握;
- 缺点:还得写sql,性能一般。
(2)编程步骤
-
step1. 导包。 mybatis,ojdbc,junit
-
step2. 添加配置文件。
注:主要是连接池的配置和映射文件的位置。
- step3. 写实体类。
注:实体类的属性名与表的字段名要一样(大小写可以忽略)。
- step4. 添加映射文件。
注:里面主要是sql语句。
<mapper namespace="test">
<!--
id: 要求唯一
parameterType: 参数类型,这儿填写实体类的完整的名字。
-->
<insert id="save" parameterType="entity.Employee">
insert into t_emp values(t_emp_seq.nextval,#{name},#{age})
</insert>
</mapper>
注意:当parameterType为基本类型时,也就是说参数为一个值的时候(比如findById的参数id),#{}里面写什么变量都可以。
- step5. 调用SqlSession对象提供的方法来访问数据库。
TestCase.java
public class TestCase {
@Test
public void test1(){
String config="SqlMapConfig.xml";
// step1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder ssfb=new SqlSessionFactoryBuilder();
// step2.创建SqlSessionFactory对象
SqlSessionFactory ssf=ssfb.build(TestCase.class.getClassLoader().getResourceAsStream(config));
// step3.获得SqlSession对象
SqlSession session=ssf.openSession();
// 调用SqlSession对象提供的方法访问数据库
Employee e=new Employee();
e.setName("Eric");
e.setAge(33);
session.insert("test.save",e);
// 添加,修改,删除都需要提交事务
session.commit();
// 关闭SqlSession
session.close();
}
}
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
<configuration>
<environments default="environment">
<environment id="environment">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
<property name="username" value="system" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 指定映射文件的位置 -->
<mappers>
<mapper resource="entity/EmpMapper.xml" />
</mappers>
</configuration>
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="test">
<!--
id:要求唯一
parameterType:参数类型,这儿填写实体类的完整的名字。
-->
<insert id="save" parameterType="entity.Employee">
insert into t_emp values(t_emp_seq.nextval,#{name},#{age})
</insert>
</mapper>
(3)工作原理
-
SqlSessionFactory读取SqlMapConfig.xml文件,文件中包含了EmpMapper.xml文件的地址;
-
然后,SqlSessionFactory会创建一系列预编译的Map对象,key是sql的id,value是对应的statement;
-
通过SqlSessionFactory获得SqlSession;
-
通过向SqlSession的相应方法中传入sqlid和相应的参数;
-
SqlSession会自动根据sqlid去预编译好的Map对象中查找对应的statment,然后执行,完成相应的功能。
八、Mybatis基本应用、Mapper映射器、Spring Mybatis(方式一)
练习:
使用MyBatis完成对部门表的增删改查操作。
a.添加部门信息。
b.查询出所有部门信息
c.依据id查询某个部门信息
d.修改某个部门信息
e.删除某个部门。
create table t_dept(
id number(8)primary key,
deptName varchar2(20),
addr varchar2(50)
);
create sequence t_dept_seq;
1.返回Map类型的结果
-
(1)MyBatis会将记录中的数据先放到一个Map对象里面
(以字段名作为key,以字段值作为value,一条记录对应一个Map对象),
然后 再将Map中的数据放到对应的实体对象里面。
-
(2)返回Map类型的结果,好处是不用实体类了,但是不方便
(因为要获得字段值,还需要调用Map对象提供的get方法,
注意:oracle数据库中,字段名统一都是大写,其他数据库不一定这样,很难确定map的key值)。
2.解决字段名与实体类的属性名不一致
-
(1)方式一: 使用别名。(就是让别名与属性名一样)。
select ename as name …
-
(2)方式二: 使用resultMap解决。
3.Mapper映射器
(1)什么是Mapper映射器?
- 符合映射文件要求的接口。
注:MyBatis会生成符合该接口要求的对象。
(2)接口具体要求
-
a.方法名要与sql的id一致。
-
b.方法的参数类型要与parameterType一致。
-
c.方法的返回类型要与resultType一致。
-
d.映射文件的namespace要等于接口的完整的名字。
(3)如何使用Mapper映射器
// MyBatis会返回一个符合
// Mapper映射器要求的对象。
EmployeeDAO dao = session.getMapper(EmployeeDAO.class);
4.Spring集成MyBatis (方式一 使用Mapper映射器)
(1)集成步骤
- step1.导包。spring-webmvc,mybatis,mybatis-spring,dbcp,ojdbc,spring-jdbc,junit。
- step2.添加spring配置文件。
注:不再需要MyBatis的配置文件,可以在spring的配置文件里面添加SqlSessionFactoryBean来代替。
<!-- 配置SqlSessionFactoryBean -->
<bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入连接池 -->
<property name="dataSource" ref="ds"/>
<!-- 注入映射文件的位置 -->
<property name="mapperLocations" value="classpath:entity/*.xml" />
</bean>
- step3.实体类
- step4.映射文件
注:mapper.xml文件的namespace要求等于接口名。
-
step5.Mapper映射器
-
step6.配置MapperScannerConfigurer
注:该bean会扫描指定包及其子包下面的所有的Mapper映射器(即接口),然后调用getMapper方法获得映射器的实现(比如,调用 EmployeeDAO dao = SqlSession.getMapper(EmployeeDAO.class))。并且,将这些对象添加到Spring容器里面(默认的id是首字母小写之后的接口名,可以使用@Repository重命名)。
<!-- 配置MapperScannerConfigurer -->
<!-- id默认是类名首字母小写 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入映射器所在的包名 -->
<property name="basePackage" value="dao"/>
</bean>
(2)只扫描特定的接口。
- step1. 开发一个注解。
- step2. 将该注解添加到需要扫描的接口之上。
- step3. 修改MapperScannerConfigurer的配置。
<!-- 配置MapperScannerConfigurer -->
<!-- id默认是类名首字母小写 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入映射器所在的包名 -->
<property name="basePackage" value="dao"/>
<!-- 只扫描带有特定注解的接口 -->
<property name="annotationClass" value="annotation.MyBatisRepository"/>
</bean>
九、Spring MyBatis(方式二)
1.Spring集成MyBatis (方式二)
(1)集成步骤
-
step1.导包。spring-webmvc,mybatis,mybatis-spring,dbcp,ojdbc,spring-jdbc,junit。
-
step2.添加spring配置文件。
注:不再需要MyBatis的配置文件,可以在spring的配置文件里面添加SqlSessionFactoryBean来代替。
- step3.实体类
- step4.映射文件
注:namespace不再要求等于接口名。
- step5.DAO接口
注:接口方法没有特定要求
- step6.写一个DAO接口的实现类
注:可以注入SqlSessionTemplate。
<!-- 配置SqlSessionTemplate -->
<bean id="sst" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="ssfb"/>
</bean>
@Repository("empDAO")
public Class EmployeeDAOMyBatisImpl implements EmployeeDAO {
@Autowired
@Qualifier("sst")
private SqlSessionTemplate sst;
}
2.使用Spring集成MyBatis的方式重写AdminDAO
SSM(SM):SpringMVC+Spring+Mybatis
-
step1. 导包,需要添加 mybatis,mybatis-spring,spring-jdbc
-
step2. 在配置文件当中,添加 SqlSessionFactoryBean
-
step3. 实体类Admin,要注意属性与表的字段名不一样,建议用别名解决
-
step4. 映射文件,放在entity包下面
AdminMapper.xml
<mapper namespace="cn.tedu.netctoss.dao.AdminDAO">
<select id="findByAdminCode" parameterType="java.lang.String"
resultType="cn.tedu.netctoss.entity.Admin">
SELECT ...
</select>
</mapper>
-
step5. Mapper映射器 (AdminDAO)
-
step6. 配置MapperScannerConfigurer
-
step7. 测试 AdminDAO
十、AJAX简介
3.ajax (asynchronous javascript and xml 异步的javascript和xml)
(1)ajax是什么?
- 是一种用来改善用户体验的技术,本质上是利用浏览器提供的一个特殊对象(XMLHttpRequest对象;
- 一般也可以称之为ajax对象)向服务器发送异步请求;服务器返回部分数据,浏览器利用这些数据对当前页面做部分更新;
- 整个过程,页面无刷新,不打断用户的操作。
注:异步请求,指的是,当ajax对象发送请求时,浏览器不会销毁当前页面,用户仍然可以对当前页面做其它操作。
(2)如何获得ajax对象?
- 需要考虑一些ie老版本的用户,因为ie是ActiveXObject对象,其他浏览器是XMLHttpRequest对象,所以要分情况讨论:
function getXhr(){
var xhr = null;
if(window.XMLHttpRequest){
//非ie浏览器
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('MicroSoft.XMLHttp');
}
return xhr;
}
(3)ajax对象的几个重要属性
-
onreadystatechange: 绑订事件处理函数,用来处理readystatechange事件。
注:当ajax对象的readyState属性值发生了任何的改变,比如从0变成了1,就会产生readystatechange事件。
-
readyState:有5个值(分别是0,1,2,3,4),用来获取ajax对象与服务器通信的进展。其中,4表示ajax对象已经获得了服务器返回的所有的数据。
-
responseText:获得服务器返回的文本数据。
-
responseXML:获得服务器返回的xml数据。
-
status:获得状态码。(例如200,404,500…)
(4)编程步骤
-
step1. 获得ajax对象,比如 var xhr = getXhr();
-
step2. 调用ajax对象的方法,发送请求
- 方式一 get请求
// (请求方式,请求地址,boolean) xhr.open('get','check.do?adminCode=king',true); xhr.onreadystatechange = f1; // f1为事件处理函数 xhr.send(null); // 把数据打包发送到服务器
注:
- true: 异步 (浏览器不会销毁当前页面,用户仍然可以对当前页面做其它操作)
- false:同步 (浏览器不会销毁当前页面,但是会锁定当前页面,用户不能够对当前页面做任何操作,尽量不用)。
- 方式二 post请求
xhr.open('post','check.do',true); // 设置请求头(消息头) xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // f1为事件处理函数 xhr.onreadystatechange=f1; xhr.send('adminCode=king');
注:按照http协议要求,如果发送的是post请求,应该包含有Content-type消息头,但是,ajax默认不会带这个消息头,所以,需要调用setRequestHeader方法来添加这个消息头。
-
step3. 编写服务器端的程序
注:不需要返回完整的页面,只需要返回部分数据。
- step4. 编写事件处理函数
if(xhr.readyState == 4 && xhr.status == 200){
// ajax对象已经获得了服务器返回的所有数据,
// 而且服务器处理正确。
var txt = xhr.responseText;
// 页面更新...
}
十一、AJAX编码问题、缓存问题、JSON
1.编码问题
(1)GET请求
-
1)为什么会有乱码?
- ie浏览器提供的ajax对象,在发送get请求时,会对中文参数值使用"gbk"来编码,其它浏览器会使用"utf-8"来编码。服务器端默认会使用"iso-8859-1"来解码。所以会有乱码。
-
2)如何解决?
-
step1. 服务器端,统一使用"utf-8"来解码。可以修改:
<Connector URIEncoding="utf-8" />
-
step2.客户端,使用encodeURI函数对中文参数值进行编码。
注:encodeURI函数是javascript内置的函数,会使用"utf-8"来编码。
-
(2)POST请求
-
1)为什么会有乱码?
- 浏览器提供的ajax对象在发送post请求时,对中文参数值会使用"utf-8"来编码,而服务器端会使用"iso-8859-1"来解码。
-
2)如何解决?
- request.setCharacterEncoding(“utf-8”)
2.缓存问题
(1)什么是缓存问题?(GET请求才有缓存问题)
- 如果使用ie浏览器提供的ajax对象发送get请求,会比较请求地址是否访问过,如果访问过,则不再发送新的请求,而是将第一次访问的结果显示出来(也就是说,第一次访问时,会将服务器返回的结果缓存下来了)。
(2)如何解决?
-
在请求地址后面添加一个随机数。
例:“getNumber.do?”+Math.random()
3.JSON (javascript object notation)
(1)json是什么?
- 是一种轻量级的数据交换格式。(json借鉴了javascript的部分语法)
- 数据交换:指的是将要交换的数据转换成一种与平台无关的数据格式(比如xml),然后发送给接收方来处理。
- 轻量级:json相对于xml而言,文档更小,解析速度更快。
(2)语法
-
1)表示一个对象
{属性名:属性值,属性值:属性值…}
- a.属性名必须使用双引号括起来。
- b.属性值可以string,number,true/false,null,object。
- c.属性值如果是string,必须使用双引号括起来。
-
2)表示对象组成的数组
[{},{},{}…]
(3)使用json
-
1)java对象如何转换成json字符串?
-
导包:
-
使用jackson提供的api(ObjectMapper)。
-
例1:
ObjectMapper om=new ObjectMapper(); String jsonStr=om.writeValueAsString(stocks);
- 例2:
List<Stock> stocks=new ArrayList<Stock>(); for(int i=0;i<3;i++){ Stock s=new Stock(); s.setCode("600977"+i); s.setName("中国嘉陵"+i); s.setPrice(8+i); stocks.add(s); } ObjectMapper om=new ObjectMapper(); String jsonStr=om.writeValueAsString(stocks); System.out.println(jsonStr);
-
-
2)将json字符串转换成javascript对象?
-
使用javascript内置对象JSON提供的parse()函数。
-
例1:
var str='{"name":"Sally","age":22}'; // 使用javascript内置对象JSON提供的方法来转换 var obj=JSON.parse(str); alert(obj.name);
-
例2:
var str='[{"name":"Sally","age":22},' + '{"name":"Eric","age":32}]'; var arr=JSON.parse(str); // 返回的是由多个javascript对象组成的数组 alert(arr[0].name);
-
案例:
十二、JQuery对ajax的支持、load方法
1.jQuery对ajax编程的支持
(1)$.ajax方法
-
1)用法:
$.ajax({});
注:{}是一个对象,其属性用来控制ajax对象如何向服务器
-
发送请求,常见的属性如下:
-
url: 请求地址
-
sync: 是否为异步访问,有两个值:
“true” 异步访问(默认)
“false” 同步访问
-
type: 请求类型
-
data: 请求参数(可以是请求字符串形式,比如:“adminCode=king&age=22”,还可以是对象形式,比如{“adminCode”:“king”,“age”:22})
-
dataType: 服务器返回的数据类型,有如下类型:
“json” json字符串
“text” 文本
“html” html文档
“xml” xml文档
“script” javascript脚本
-
success: 绑订事件处理函数(服务器已经返回了所有数据,并且没有出错)。
-
error: 绑订事件处理函数(服务器出错了)
-
-
-
比如:
$.ajax({//用不到的参数可以不写
url:"check.do",
(sync: "true",)
type:"get",
data: "adminCode=king",
dataType:"text",
success: function(obj){
// 处理服务器返回的数据
// obj就是服务器端返回的数据。如果返回的是json字符串,会自动转换成javascript对象。
// 前提是必须要设置dataType为json格式
},
error: function(){//用于处理服务器出错时的函数
}
});
(2)load方法
-
1)该方法会向服务器发送异步请求,并且将服务器返回的数据直接添加到符合要求的节点之上。
-
2)用法
$obj.load(url,[data]);
- url : 是请求地址。
- data: 是请求参数。有两种写法(请求字符串和对象的形式)
- (比如“adminCode=king&age=22”或{“adminCode”:“king”,“age”:22})
注:$obj,是jQuery对象