Spring
##Spring IOC
控制反转
管理对象及对象的关系,降低他们的耦合度
IOC是其他功能的基础
Spring容器是IOC的核心
##Spring AOP
面向切面(方面)变成
Filter可以统一处理多个Servlet共同的业务
AOP可以统一处理一切对象的共同业务
可以降低共同业务和对象之间的耦合度
##Spring MVC
自动实现MVC给代码分层,能进一步降低Servlet及JSP内部的耦合度
Spring整合
Spring可以整合JDBC提高开发效率,
Spring可以整合MyBatis,Hibernate,提高开发效率
Spring可以整合Struts2,提高开发效率
Spring可以降低这些技术中核心对象的耦合度
Spring容器:
在Spring中,任何的JAVA和JAVABEANN都被当成Bean处理,这些Bean通过容器管理和使用,
Spring容器实现了IOC和AOP机制,这些机制可以简化Spring对象创建和Bean对象之间的解耦;
Spring容器有BeanFactory和ApplicationContext两种类型
使用的时候通过maven先导包spring-webmvc的包3.2.8版本
Spring容器工作步骤
- 配置xml文件,
- new ApplicationContext对象,,
- 对象加载配置文件,根据标签,实例化后的bean存到对象里,容器里就有对象了
- 获取:需要的话调用方法getBean(id),通过对象id来获取。
<!-- 管理bean的生命周期
让spring自动调用该bean的初始化及销毁方法
通过另外两个属性调用初始化,销毁方法
init-method:声明初始化方法,在容器创建bean之后自动调用
destroy-method:声明销毁方法,spring容器关闭时,自动调用销毁-->
<bean class="bean.Example" id="exa"
init-method="init" destroy-method="destroy"></bean>
指定销毁回调方法,仅适用于单例模式的bean。
IOC:Inversion of Control控制反转;
指程序中对象的获取方式发生反转,由最初的new方式创建,转变为由第三方框架创建,注入(DI),降低了对象之间的耦合度。
Spring容器是采用DI方式实现了IOC控制,IOC是Spring框架的基础和核心
DI:Dependency Injection,依赖注入,
基本原理就是将一起工作具有关系的对象,通过构造方法参数或方法参数传入建立关联,因此容器的工作就是创建Bean时注入那些依赖关系,
IOC时一种思想,而DI是实现IOC的主要技术途径,
DI由两种注入方式,Setter注入和构造器注入。
Setter注入
通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即可实现setter的注入
<!-- 1.setter注入:通过bean的set方法,给他注入参数 -->
<bean class="bean.Computer" id="computer">
<property name="mainboard" value="技嘉"/>
<property name="hdd" value="希捷"></property>
<property name="ram" value="金士顿"/>
</bean>
@Test
public void test7() {
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
MobilePhone phone=(MobilePhone) ctx.getBean("phone");
System.out.println(phone.getCpu());
System.out.println(phone.getRam());
}
自动装配(见eclipse Spring1 -TestCase)
Spring IOC容器可以自动装配,相互协作bean之间的关联关系,
Autowire可以针对单个bean进行设置,它的方便之处在于减少xml的注入配置,
在xml配置文件中,可以在</bean>元素中使用autowire属性指定自动装配规则,
Spring Unit2上
引用的方式注入集合
<!-- 引用的方式注入集合类型的值 -->
<util:list id='citiesBean'>
<value>北京</value>
<value>上海</value>
<value>长沙</value>
</util:list>
<util:set id="interestBean">
<value>钓鱼</value>
<value>做饭</value>
<value>台球</value>
</util:set>
<util:map id="scoreBean">
<entry key="english" value="100" />
<entry key="math" value="90" />
</util:map>
<util:properties id="dbBean">
<prop key="user">tom</prop>
<prop key="password">1234</prop>
</util:properties>
<bean id="msg" class="ioc.MessageBean">
<property name="cities" ref="citiesBean" />
<property name="interest" ref="interestBean"/>
<property name="score" ref="scoreBean"></property>
<property name="db" ref="dbBean"></property>
</bean>
<!-- 读取properties文件的内容 让spring容器读取指定位置的properties内容
存放到properties对象中,
classpath:内部的约定,根据classpath找-->
<util:properties id="config" location="classpath:config.properties"/>
@Test
public void test1() {
//启动spring容器
ApplicationContext ac=new
ClassPathXmlApplicationContext("applicationContext.xml");
//通过容器获取一个bean实例
//getBean的重载方法,此处就不用强转类型了
MessageBean mb=ac.getBean("msg",MessageBean.class);
System.out.println(mb);
}
Spring表达式:读取bean或者集合的属性
一个bean读另外一个bean的属性(见Eclipse spring2下的ExampleBean类)
<!-- Spring表达式来访问其他的bean属性 -->
<bean id="eb" class="ioc.ExampleBean">
<property name="ename" value="#{msg.name}"></property>
<property name="city" value="#{msg.cities[1]}"></property>
<!-- 下面读取math的分数也可以不写成#{msg.score.math}
把配置文件的内容已经读到bean里面了,通过util:map id="scoreBean 的id也可以读取-->
<property name="score" value="#{scoreBean.math}"></property>
<property name="pageSize" value="#{config.pageSize}"></property>
</bean>
1基于注解的配置;
##组件扫描
容器启动之后,把配置文件读一遍
当发现配置文件中有<.context:component-scan base-backage=”***”>
会扫描这个包,下面所有的类,这些类包含特定的注解的话会纳入容器进行管理
(相当于在配置文件中配置了一个bean)
2如何进行组件扫描
Step1在xml配置文件中,添加<.context:component-scan base-backage=”***”>
Step2在类名前添加如下的注解
自动扫描的注解标记
@Component 通用注解,
@Repository 持久层组件注解,访问数据库的
@Service 业务层组件注解 做处理的
@Controller 控制层组件注解
3对象管理的几个注解
@Scope 作用域
@Lazy 延迟加载
@PostConstruct 初始化方法
@PreDestroy销毁方法
##使用注解来完成依赖注入
###Autowired和@Qualiifier
方式一完成set方式的注入
将Autowired添加到set方法前,使用Qualifier指定要注入的bean的id
这两个注解也可以直接添加到属性前
方式二:完成构造器方式注入,将@Autowired添加到构造器前面
@Resource
只支持set方式的注入,该注解可以添加到set方法前面或者属性前
使用注解的方式来使用spring表达式
SpringMVC
是一个用来简化web应用开发的mvc框架
五大组件
- DispatcherServlet,相当于以前的mainServlet (前端控制器)C
- HandlerMapping 告诉1请求应该交给哪个modle来处理,映射路径的
- Controller 处理器处理业务逻辑的处理 M
MVC M: Controller C: DispatcherServlet V: JSP
- ModelAndView 封装处理结果
- ViewResolver 视图解析器
五大组件的的关系:
- 前端控制器DispatcherServlet收到请求后,依据HandlerMapping的配置调用相应的Controller来处理
- Controller将处理结果封装成ModelAndView对象,返回给前端控制器。ModelAndView对象里面通过包含两部分信息(处理结果和视图名,视图名是一个字符串)
- 前端控制器依据视图解析器的解析,调用相应的视图对象(比如是一个JSP)来对处理结果进行展现。
编程步骤:
- 导包(springmvc相关的jar包)。
- 添加spring的配置文件比如,(applicationConxtext.xml)。
- 需要配置前端控制器DispatcherServlet(在web.xml中配置)
- 写Controller(处理器)
- 写JSP.
- 在spring配置文件中,配置HandlerMapping和ViewResolver
Tomcat启动的时候,先把前端控制器DispatcherServlet创建好,它会启动spring容器,
通过浏览器发请求hello.do依据HandlerMapping的指示,调用Controller处理器来处理请求,处理器把处理结果封装成ModleAnndView对象,返回给DispatcherServlet,前端控制器DispatcherServlet依据视图解析器,告诉前端控制器要调哪个jsp,响应给浏览器
###基于注解的springmvc的应用
1导包(springmvc相关的jar包)。
2.添加spring的配置文件比如,(applicationConxtext.xml)。
3.需要配置前端控制器DispatcherServlet(在web.xml中配置)
4.写处理器(Controller0
@Controller注解声明Controller组件,这样使得Controller定义更加灵活,
4.1可以不用实现Controller接口.
4.2可以添加多个处理方法,也就是说一个Controller可以处理多个请求。
4.3处理方法的名称不做要求,不必是HandleRequest,返回值可以是String或者ModelAndView,
如果返回值没有处理结果,只是返回一个试图名的话,可以返回String。
4.4,在处理器类名前添加@Controller
4.5. 在类名前或者方法前添加@RequestMapping注解,告诉前端控制器,请求地址与处理方法的对应关系。
5.写 JSP
6.在spring配置文件中,配置ViewResolver.
Day04:
如何读取请求参数值,如何向页面传值
读取请求参数,第一种方式
@RequestMapping("/login.do")
public String checkLogin(HttpServletRequest request) {
/**
* 前端控制器调用处理器之前,利用反射分析这个方法有哪些参数,
* 分析完后发现有一个请求对象,把请求对象作为参数传进来,
* 这是第一种方式,
*/
System.out.println("HelloController的checkLogin的方法");
String adminCode =request.getParameter("adminCode");
String pwd =request.getParameter("pwd");
System.out.println("账号:"+adminCode+"密码:"+pwd);
return "index";//返回另一个视图名,及jsp
}
jsp中
<body
style="font-size: 30px;font-tyle:italic;">
<form action="login.do" method="post">
账号:<input name="adminCode"/><br/>
密码:<input name="pwd" type="password"/><br/>
<input type="submit" value="登录">
</form>
</body>
2.第二种方式
@RequestMapping("/login2.do")
/**
* 读取请求参数的第二种方式
* 使用请求参数名字作为方法的入参(参数名)。
* 如果参数名字不一致,可以在参数前加注解@Re'questParam(*),
* *号是哪个请求参数的名字。
* 例如(String adminCode,@Re'questParam(pwd) String pwd1)
*/
public String checkLogin2(String adminCode,String pwd) {
System.out.println("checkLogin2方法");
System.out.println("账号:"+adminCode+",密码"+pwd);
return "index";
}
<body
style="font-size: 30px;font-tyle:italic;">
<form action="login2.do" method="post">
账号:<input name="adminCode"/><br/>
密码:<input name="pwd" type="password"/><br/>
<input type="submit" value="登录">
</form>
</body>
第三种方式:
先建一个java bean,
要求属性和请求参数一模一样。要有对应的get set方法
2.在处理方法里用java bean作为处理放出
@RequestMapping("/login3.do")
public String checkLogin3(Admin admin) {
/**
* 读取请求参数的第三种方式,封装成java bean的方式,属性要和请求参数名一样
* 有对应的get set方法
*/
System.out.println("checkLogin3的方法");
System.out.println("账号"+admin.getAdminCode()+"密码:"+admin.getPwd());
return "index";
}
向页面传值
第一种方式:使用请求对象绑定数据,
默认情况下前端控制器会使用转发机制来跳转页面,不需要获得转发器(…forward)
@RequestMapping("/login4.do")
/**
* 向页面传值的第一种方式,使用request对象绑定数据
* @return
*/
public String checkLogin4(Admin admin,HttpServletRequest request) {
System.out.println("checkLogin4的方法");
System.out.println("账号:"+admin.getAdminCode());
//向页面传值
//利用请求对象绑定数据,然后转发给index.jsp,index.jsp通过请求对象获取数据
request.setAttribute("adminCode", admin.getAdminCode());
//默认情况下是转发的方式跳转到index.jsp
return "index";
第二种方式:使用ModelMap对象作为方法的参数(springmvc提供的)
@RequestMapping("/login5.do")
/**
* 向页面传值的第二种方式,使用ModelMap作为方法的参数
*/
public String checkLogin5(Admin admin,ModelMap data) {
System.out.println("check5的方法");
System.out.println("账号"+admin.getAdminCode());
/**
*
* 等同于request.setAttribute
*/
data.addAttribute("adminCode",admin.getAdminCode());
return "index";
}
第三种方式,使用session对象绑定数据
@RequestMapping("/login6.do")
/**
* 向页面传值的第三种方式,
* 使用session绑定数据
*
* @return
*/
public String checkLogin6(Admin admin,HttpSession session) {
System.out.println("checkLogin的6的方法");
System.out.println(admin.getAdminCode());
session.setAttribute("adminCode",admin.getAdminCode());
return "index";
}
第四种方式,用ModelAndView
@RequestMapping("login7.do")
/*
* 向页面传值的第四种方式,
* 使用ModelAndView对象作为方法的返回值。
*/
public ModelAndView checkLogin7(Admin admin) {
System.out.println("check7的方法");
System.out.println("账号:"+admin.getAdminCode());
Map<String,Object> data=new HashMap<String,Object>();
//相当于request.setAttribute
data.put("adminCode", admin.getAdminCode());
ModelAndView mav=new ModelAndView("index",data);
return mav;
}
Day04如何重定向
- 情形1:如果方法的返回值是String
return “redirect:toIndex.do”
/**演示重定向
* 重定向的第一种方式:
* 如果处理方法的返回值是String
* 需要在重定向地址前添加前缀"redirect:"
* 例如 return "redirect:index";
*/
@RequestMapping("/login8.do")
public String checkLogin8() {
System.out.println("checkLogin8的方法");
return "redirect:toIndex.do";
}
@RequestMapping("/toIndex.do")
public String toIndex() {
System.out.println("这是接受checkLogin8的转发");
return "index";
}
- 如果方法的返回值是ModelAndView
首先构造一个对象RedirectView rv=new RedirectView(toIndex.do)
ModelAndView mav=new ModelAndView(rv);
/**
* 重定向的第二种方式
* @return
*/
@RequestMapping("login9.do")
public ModelAndView checkLogin9() {
System.out.println("checkLogin9的方法");
RedirectView rv=
new RedirectView("toIndex.do");//参数就是:重新向的地址
//把rv这个对象传到ModelAndView中
return new ModelAndView(rv);
}
系统分层:
##如何分层
1.将系统划分成表示层M和C(负责数据展现和操作界面),业务层(负责业务逻辑的处理),持久层(负责数据库访问)
2.上一层通过接口调用下一层提供的服务(比如表示层通过接口调用业务层,业务层通过接口调用持久层),这样一来,下一层发生任何改变不影响上一层,方便代码的维护
Model 业务逻辑的处理
再分成 业务层,持久层(数据访问)
解决表单提交的乱码问题
只需要配置一个过滤器,由spring提供,
- 表单提交方式碧血为post
- 过滤器的鞭名马的设置与客户端一致
在web.xml下配置
<!-- 过滤器:中文乱码解决 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Session验证
- 登陆成功后,在session中保存数据
拦截器做登陆验证:
什么是拦截器?属于spring的特殊组件
是前端控制器,收到请求之后,先调用拦截器的处理方法。然后再调用处理器Controlller来处理。
注:过滤器属于Servlet规范当中定义的特殊的组件,拦截器属于spring容器管理的特殊的组件。
如何写一个拦截器:
Step1,写一个java类,实现HandlerInterceptor接口。
Step2.在接口方法中,实现拦截处理逻辑(比如session验证)。一共三个方法.
- preHandle
- postHandle
- afterCompletion
preHandle方法:前端控制器,收到请求之后,会先调用拦截器的preHandle方法,如果这个方法的返回值为true,则表示继续向后调用,否则请求处理完毕
postHandle方法:处理器Controller的方法已经执行完毕,准备把ModelAndView对象返回给前端控制器之前调用postHandle方法。处理Controller返回的结果,可以在该方法里面对ModelAndView进行修改。
afterCompletion,整个请求处理完毕,执行afterCompletion方法。
案例见springcase-springmvc03