非本人总结的笔记,抄点笔记复习复习。感谢传智博客及黑马程序猿
感谢传智博客及黑马程序猿
Spring整合web项目
引入:在做开发中,使用mvc+dao模式,提交表单到Servlet中,Servlet调用Service里面的方法,在Service里面调用dao里面的方法
第一步:导入Spring整合web项目的jar包
spring的web项目jar包第二步:创建Servlet、Service、dao
package cn.itcast.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class UserServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("servlet执行了...............");
//得到service对象
WebApplicationContext context =
WebApplicationContextUtils.getWebApplicationContext
(this.getServletContext());
UserService service = (UserService) context.getBean("userService");
service.testservice();
}
/**
*
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
package cn.itcast.web;
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void testservice() {
System.out.println("service........");
userDao.testdao();
}
}
package cn.itcast.web;
public class UserDao {
public void testdao() {
System.out.println("dao.............");
}
}
第三步:配置applicationContext.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 创建dao和service对象 -->
<bean id="userDao" class="cn.itcast.web.UserDao"></bean>
<bean id="userService" class="cn.itcast.web.UserService">
<!-- 注入dao对象 -->
<property name="userDao" ref="userDao"></property>
</bean>
</beans>
第四步:配置web.xml监听器配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<!-- 使用全局初始化参数配置文件位置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 配置监听器 ContextLoaderListener -->
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>UserServlet</servlet-name>
<servlet-class>cn.itcast.web.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
问题:
在Servlet中获取Service时候因为
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
每次访问Servlet的时候,都会创建一次对象,造成资源浪费,只需要创建一次就可以了
日志信息解决方法:
在web项目中只有一个对象是ServletContext对象。这个对象范围是整个web项目。
做法:可以在服务器启动时候,把applicationContext对象放到servletcontext里面去。之前学过监听器。监听到servletcontext对象创建和销毁
创建类,实现接口ServletContextListener,监听到servletcontext对象创建,只要创建把applicationContext对象放到里面去。
第一步:配置监听器ContextLoaderListener
public class ContextLoaderListener extends ContextLoaderListener implements ServletContextListener{
}
第二步:指定配置文件位置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
第三步:使用WebApplicationContextUtils得到context对象
WebApplicationContext context = WebApplicationContextUtil.getWebApplicationContext(this.getServlet());
AOP
AOP相关概念
什么是AOP:
面向方面编程。在一个基本功能之上,添加一个额外的功能,但是没有额外的功能,基本功能也可以正常运行。
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码
比如有用户管理系统,有添加用户的功能,如果添加完成用户之后,可以记录添加的日志(东方不败在2016-11-11添加了用户),但是如果没有记录日志,添加用户的功能也可以运行。
AOPAop底层使用动态代理,增强一个类中的方法,有两种:
第一种:JDK动态代理,使用在有接口情况下,生成接口实现类的代理对象
第二种:cglib动态代理,使用在没有接口情况下,生成类的子类代理对象
JDK的动态代理
例:
public DaiLi implements InvocationHandler{
private Bird bird;
public DaiLi(Bird bird) {
this.bird = bird;
}
public Object invoke(Object proxy, Method method, Object[] args) throw Throwable{
bird.fly();
Sysotem.out.println("增强输出");
return null;
}
}
Class[] interfaces = {Bird.class};
Bird bird = (Bird) Prxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new DaiLi(new Ying));
bird.fly();
针对有接口情况,生成接口实现类的代理对象
CGLIB动态代理
针对没有接口情况,生成类子类代理对象
public ProductService createProductService() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(productSercice.getClass());
enhancer.setCallBack(this);
ProductService procutService = (ProductService) enhancer.create();
return productService;
}
public Object intercept(Object o, Method method, Object[] obj, MethodProxy methodProxy) throws Throwable {
Object object = methodProxy.invokeSuper(o, obj);
System.out.println("CGLIB增强的方法。。。");
return object;
}
public static void main(String[] args) {
MyCGLIB cglib = new MYCGLIB(new ProductService());
ProductService productService = cglib.createProductService();
productService.buy();
}
AOP术语
Joinpoint(连接点):在一个类中有哪些方法可以增强,这些方法称为连接点
Pointcut(切入点):在一个类中的所有可以被增强的方法中,哪些方法具体做增强
Advice(增强/通知):写具体的增强逻辑。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的通知)
Target(目标对象):代理的目标对象(要增强的类)
Weaving(织入):是把增强应用到目标的过程。把advice应用到target
Proxy(代理):一个类被AOP织入增强后,就产生了一个结果代理类
Aspect(切面):是切入点和增强的结合。把具体的逻辑增强到具体的方法上
Introduction(引介):引介是一种特殊的通知在不修饰类代码的前提下,Introduction可以在运行期为类动态的添加一些方法或属性
Spring的传统方式Aop
第一步:导入两个jar包
jar包第二步:配置文件,加入新的约束
约束Spring的AOP切面类型:
Advisor:不带切入点切面,对目标类所有方法进行拦截
PointcutAdvisor:有切点的切面,可以指定拦截目标类那些方法
不带切入点的切面
不带切入点的切面,对目标类所有方法进行拦截
第一步:生成实现类和增强类对象
<!-- 创建接口实现类的对象 -->
<bean id="userDao" class="cn.xxx.userDaoImpl"></bean>
<!-- 创建通知类的对象 -->
<bean id="myBefore" class="cn.xx.MyBefore"></bean>
第二步:配置增强类和实现了的关系
<!-- 配置切面 -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 指定哪个通知在哪些方法上 -->
<!-- 指定是生成哪个接口类的实现对象 -->
<property id="proxyFaces" value="cn.xxx.UserDao"></property>
<!-- 配置使用的哪一个通知 -->
<property id="interceptorNames" value="myBefore"></property>
<!-- 配置目标类 -->
<property name="target" ref="userDao"></property>
</bean>
第三步:测试
@Resource(name="proxyFactoryBean")
private UserDao userDao;
@Test
public void test() {
userDao.run();
}
带切入点切面
第一步:创建类的对象
<!-- 配置带切入点切面 -->
<bean id="personDao" class="cn.xx.PersonDao"></bean>
<bean id="myAround" class="cn.xx.MyAround"></bean>
第二步:配置切入点(配置类里面哪些方法进行增强)
配置切入点第三步:配置切面
配置切面Spring基于aspectj的AOP操作(重点)
AspectJ是一个面向切面的框架,它扩展了Java语言。
AspectJ是一个基于Java语言的AOP框架
Spring2.0以后新增了对AspectJ切点表达式支持
@AspectJ 是AspectJ1.5新增功能,通过JDK5注解技术,允许直接在Bean类中定义切面
新版本Spring框架,建议使用AspectJ方式来开发AOP
基于aspectj的注解方式
第一步:导入相关的jar包
jar包第二步:在配置文件中引入约束
约束第三步:开启aspectj的注解
aspectj的注解使用注解实现不同的通知
- @Before 前置通知,相当于BeforeAdvice
- @AfterReturning 后置通知,相当于AfterReturningAdvice
- @Around 环绕通知,相当于MethodInterceptor
- @AfterThrowing抛出通知,相当于ThrowAdvice
- @After 最终final通知,不管是否异常,该通知都会执行
通过execution函数,可以定义切点的方法切入
• 语法:
– execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)
• 例如
– 匹配所有类public方法 execution(public * *(..))
– 匹配指定包下所有类方法 execution(cn.itcast.dao.(..)) 不包含子包
– execution(* cn.itcast.dao..(..)) ..表示包、子孙包下所有类
– 匹配指定类所有方法 execution(cn.itcast.service.UserService.(..))
– 匹配实现特定接口所有类方法 execution(cn.itcast.dao.GenericDAO+.(..))
– 匹配所有save开头的方法 execution(* save*(..))
常用的写法:
匹配所有类的所有的方法 execution(* .(..))
匹配某个类的里面所有的方法 execution(* cn.itcast.UserDao.*(..))
匹配某个类里面的某一个方法execution(*cn.itcast.UserDao.update(..))
基于切入点的注解
有多个类型通知,都需要对一个类里面某一个方法进行增强
使用注解@Pointcut,写在一个方法上面
例子使用时候,在增强的方法上面使用类名.方法名称调用
例子基于aspectj的xml方式
第一步:导入jar包(包含基本jar包,包含aop的jar包,包含aspectj的jar包)
第二步:在配置文件中引入约束(beans、aop约束)
第三步:创建类,创建增强类
第四步:配置两个类的对象
配置第五步:使用aspectj的方法xml进行配置
- 配置切面
- 配置切入点
- 使用哪个增强用在哪个方法上面
Spring的jdbcTemplate模板
spring的jdbcTemplate,可以实现对数据库的crud的操作。底层就是jdbc操作,对jdbc进行了封装。
//构造连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();
//设置数据库相关信息
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring");
dataSource.setUserName("root");
dataSource.setPassword("root");
//创建jdbcTemplate对象
JdbcTemplate template = new JdbcTemplate(dataSource);
String sql = "create table user (id int, username varchar(100))";
//执行sql语句
template.execute(sql);
使用jdbc实现增删改操作
添加方法
JdbcTemplate template = new JdbcTemplate(dateSource);
String sql = "insert into user (?, ?)";
int rows = template.update(sql ,1, "Lucy");
修改方法
JdbcTemlate template = new JdbcTemplate(dateSource);
String sql = "update user set username = ? where id = ?";
template.update(sql, "东方不败", 1);
删除方法
JdbcTemlate template = new JdbcTemplate(dateSource);
String sql = "delete from user where id = ?";
template.update(sql, 1);
Spring的jdbc模板
第一步:导入相关的jar包
jar包第二步:配置数据库信息
调用模板里面的方法实现,如果实现增加、修改、删除调用里面的update方法
update()方法第一个参数是sql语句,第二个参数是参数值的可变参数
Jdbc模板的连接池配置
有c3p0、dbcp...等开源连接池
第一个:配置dbcp连接池
1、导入dbcp连接池的jar包
dbcp jar包2、配置连接池
连接池配置3、注入dbcp模板
dbcp模板 dbcp 模板第二个:配置c3p0连接池
1、导入c3p0的jar包
c3p0 jar包2、配置连接池
配置连接池<!-- 配置数据库连接池(c3p0) -->
<bean id="dataSouce" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 基本信息 -->
<!-- 必须加jdbc.xxx -->
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="driverClass" value="${jdbc.driverClassName}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<!-- 其他配置 -->
<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
<property name="initialPoolSize" value="3"></property>
<!--连接池中保留的最小连接数。Default: 3 -->
<property name="minPoolSize" value="3"></property>
<!--连接池中保留的最大连接数。Default: 15 -->
<property name="maxPoolSize" value="5"></property>
<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
<property name="acquireIncrement" value="3"></property>
<!-- 控制数据源内加载的PreparedStatements数量。如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
<property name="maxStatements" value="8"></property>
<!-- maxStatementsPerConnection定义了连接池内单个连接所拥有的最大缓存statements数。Default: 0 -->
<property name="maxStatementsPerConnection" value="5"></property>
<!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
<property name="maxIdleTime" value="1800"></property>
</bean>
Jdbc模板简化开发
第一步:在dao中继承类,不需要手动注入jdbcTemplate了
public class PersonDao extends JdbcDaoSupport{
}
第二步:在配置文件中,直接在dao里面注入dataSource
<bean id="personDao" class="cn.xx.PersonDao">
<property name="dataSource" ref="dataSource"></property>
</bean>
第三步:在dao方法里面得到jdbcTemplate的对象
this.getJdbcTemplate().update("insert into user values(?, ?)", 3, "Tom");
使用jdbc模板实现查询操作
在jdbcTemplate里面有接口,而没有提供实现的类,需要自己封装数据
第一个操作:查询单值操作
方法int count = this.getJdbcTemplate().queryForInt("select count(*) from user");
第二个操作:查询某一个对象
方法方法里面有三个参数:第一个参数是sql语句,第二个参数RowMapper是接口,数据返回结果集,需要手动封装返回结果,第三个参数是参数值
RowMapper接口String sql = "select * from user where id = ?";
Orders orders = this.getJdbcTemplate().queryForObject(sql, new MyRowMapper(), 1);
MyRowMapper类
public class MyRowMapper implements RowMapper<Orders> {
//封装数据
public Orders mapRow(ResultSet rs, int mun) throws SQLException{
//把结果集rs里面的数据,手动封装到orders里面
//把结果集里面的数据取出来
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
//封装到Orders里面
Orders o = new Orders();
o.setId(id);
o.setUsername(username);
o.setPassword(password);
return 0;
}
}
第三个操作:查询所有数据
方法String sql = "select * from user";
/**
实现过程:
首先得到每条记录的结果集
把每条记录封装到一个对象里面
这个过程做循环操作
最终把封装的多条记录,放到List集合里面
*/
List<Orders> list = this.getJdbcTemplate().query(sql, new MyRowMapper());
网友评论