Sprint框架
spring的相关概述
spring是一个开放源代码的设计层面的框架,解决的是业务逻辑和其他各层的松耦合问题,它将面向接口编程的思想贯穿整个系统中,spring是一个2003年兴起的轻量级的框架,分层的一站式的开源框架,spring是一种以非侵入式的方式来管理你的代码,spring提倡最少侵入,意味着可以在适当的时候安装或者卸载spring
1.开放源代码
2.什么是框架
支撑与限定作用,帮助开发者更加关注业务逻辑的开发
3.松耦合问题
耦合:关联关系,低耦合高聚合
4.面向接口编程
interface:用来定义一种规范 实现类implements
5.轻量级
程序小 对环境依赖少
6.非侵入式
提倡最少侵入
spring的作用
传统方式如何实现javaEE企业级开发?
servlet(MVC层)-视图层 业务层-(没有相关技术) 持久层(JDBC)
Spring框架实现javaEE企业级开发:
springmvc -视图层 业务层中(spring aop/TX) 持久层(mybatis)
spring的优势
spring能够帮助我们低侵入/低耦合,根据配置文件的方式创建以及组装对象之间的依赖关系
spring面向切面编程能够帮助我们无耦合的实现日志记录,性能统计,安全控制
spring能够简单的强大的声明式事务管理
spring提供了第三方web框架的无缝集成,提供了springmvc框架
spring能够方便的和java mail,任务调度,缓存框架技术整合
spring的体系
Data Access/Intergration:JDBC ORM OXM JMS
web:websocket servlet web Portlet
aop:aspects messaging
Core contrainer :beans core context spel
Test
spring的核心
loc:控制反转,把对象与对象和维护对象之间的关系的权力转移到spring容器中
DI:依赖注入
总结:对象的关系依赖与容器的注入,由容器管理,对象不需要自己创建
Aop:面向切面编程
可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑的各个部分耦合度降低,提高程序的可重用性。提高开发效率。
日志记录,性能统计,安全控制,事务处理,异常处理
spring的底层技术
xml dom4j 反射 工厂模式
xml
:是可扩展的标记语言,类似html。
设计宗旨是传输数据,而非显示数据,需要自定义标签,且xml被设计为具有自我描述性。
<?xml version="1.0" encoding="UTF-8" ?>
<first id="1">
<bean id="2">
</bean>
<bean id="3">
</bean>
</first>
dom4j
专门用来解析xml的
package com.wolfcode.test.dom4jtest.com.wolfcode.test;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.io.File;
public class Dom4jTest {
@Test
public void test1_dom4j(){
//创建一个读取解析xml的工具类
SAXReader saxReader = new SAXReader();
//使用该对象读取xml
try {
Document document = saxReader.read(new File("D:\\idem破解版\\实训8.1\\src\\test1.xml"));
//通过调用document中的方法获取根节点
Element rootElement = document.getRootElement();
//打印根节点的名称
System.out.println(rootElement.getName());
//获取根节点中的属性
String id = rootElement.attributeValue("id");
System.out.println(id);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
反射技术
package com.wolfcode.test.dom4jtest.com.wolfcode.test;
import org.junit.Test;
import java.lang.reflect.Field;
public class ReflectTest {
@Test
public void test1() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//首先加载到该新类型
Class<?> aClass = Class.forName("com.wolfcode.test.dom4jtest.Student");
//通过反射的方式创建对象
Object o = aClass.newInstance();
//打印
System.out.println(o);
//获取对象中的所有属性
Field[] declaredFields = aClass.getDeclaredFields();
//遍历
for(Field f:declaredFields){
System.out.println(f.getName());
}
}
}
spring的入门操作
a.导入jar包
spring-bean spring-core spring-context
commons-logging的日志包 spring-jcl
b.在src新建一个xml的配置文件(beans.xml)–bean表示的是对应的每个类型的对象
c.代码:
//加载到beanx.xml
ClasspathResource resource = new ClassPathResource("beans.xml")
//创建xmlBeanFactory
XmlBeanFactory factory = new XmlBeanFactory(resource)
//从工厂中获取对象
Object o = factory.getBean("")
(上述代码为旧版本代码,不适用实际开发流程,以下为常用代码)
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Person3 p3 = (Person3)applicationContext.getBean("p3");
标签中id以及name属性都是该bean的唯一标识,id和name的区别是什么呢?
id必须是一个数字,name可以是一个字符串。(spring3.1版本之前)
getBean的重载方法
Object a1 = (Object)factory.getBean("a1");//根据名称查找,需要强转且不太安全
factory.getBean(Object.class);//根据类型查找,可能会报错—要求容器中只能有一个该类型
Object a11 = factory.getBean("a11",Object.class);//根据类型和名称查找(最稳妥的方式)
Object可为任意实例类
常见的异常
//bean出现了多个,spring容器不知道获取那样一个
//根据名称无法匹配到查询到对应的bean
spring的实例方式
1.构造器实例化
需要使用无参的构造方式,如果在该类中加入了有参数的构造方法,那么原有的无参构造方法就会被覆盖。那么反射机制创建对象,需要使用无参的构造方法,所以会报错,要解决这个问题。
a.删除多余的有参构造方法;b.添加无参构造方法
在配置文件中添加配置
2.实现FactoryBean接口实例化
package com.wolfcode.test.Spring;
import org.springframework.beans.factory.FactoryBean;
public class MyFactory implements FactoryBean<Animal> {
@Override
public Animal getObject() throws Exception {
return new Animal(12,"hellocat");
}
//判断类型的方法-提供给spring容器使用
@Override
public Class<?> getObjectType() {
return Animal.class;
}
}
备注:需要在beans.xml中进行配置
3.静态工厂方式创建Bean(通过反射的方式)
首先定义了一个类型(静态工厂),定义了一个静态的方法,在静态方法中创建了一个对象将该静态工厂配置到bean.xml的核心配置文件中,
package com.wolfcode.test.Spring;
/*
静态工厂创建实例
*/
public class MyStaticFactory {
public static Animal createAnimal(){
return new Animal();
}
}
4.实例工厂
<bean id="factory" class="com.wolfcode.test.spring.MyFactory2"></bean>
<bean id="cat3" factory-bean="factory" factory-method="createAnimal"></bean>
package com.wolfcode.test.Spring;
public class MyFactory2 {
//普通的成员方法
public Animal createAnimal(){
return new Animal();
}
}
备注:先创建工厂的实例(对象),再通过工厂的实例创建目标bean(对象)
spring的作用域/初始化与销毁
作用域的概念:
创建的对象相对于其他对象的可见范围
作用域分类
单例singletion:spring容器中只有一个实例,getBean(Class)–spring默认就是单例模式
多例prototype:容器中有多个相同类型的实例,getBean方法的时候创建新的实例
request session application websockt
初始化:准备的过程
销毁:
方式1:
<bean id="jdbc" class="com.wolfcode.test.Spring3.MyJDBC" init-method="init" destroy-method="close" scope="prototype" ></bean>
package com.wolfcode.test.Spring3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring3 {
@Test
public void test1() {
//ClassPathResource resource = new ClassPathResource("beans.xml");
//XmlBeanFactory factory = new XmlBeanFactory(resource);
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//@Cleanup注释销毁
MyJDBC jdbc = (MyJDBC) applicationContext.getBean("jdbc");
System.out.println(jdbc);
//调用获取链接的方式
jdbc.getConnetion();
}
}
bean配置文件中destroy-method="close"执行结束自动关闭链接进行销毁
手动注销:
public class TestSpring3 {
@Test
public void test1() {
//ClassPathResource resource = new ClassPathResource("beans.xml");
//XmlBeanFactory factory = new XmlBeanFactory(resource);
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//@Cleanup
MyJDBC jdbc = (MyJDBC) applicationContext.getBean("jdbc");
System.out.println(jdbc);
//调用获取链接的方式
jdbc.getConnetion();
//手动注销容器
applicationContext.registerShutdownHook();
}
}
registerShutdownHook()
为什么bean配置了作用域为多例后,销毁方法并没有执行?
因为配置多例后,由spring容器创建的对象并没有被保存
spring的懒加载
懒加载:spring延迟创建bean的实践,通常在初始化的时候就常见,懒加载在容器初始化的时候,暂时不创建该bean(对象)
懒加载应用的场景:如果某个bean在系统运行的周期都有可能不运行,该bean可以设置为懒加载
懒加载的操作:
<bean id="p2" class="com.wolfcode.test.Spring4.Person2" lazy-init="true"></bean>
default-lazy-init="true"//全局
即刻加载/懒加载?
懒加载优点:节省了资源
缺点:响应的整个时间变长
特点:第一次使用的周期较长,第二次第三次,后续使用正常
package com.wolfcode.test.Spring4;
public class Person2 {
private String name;
private Integer age;
public Person2(){
System.out.println("对象被创建");
}
}
package com.wolfcode.test.Spring4;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*
测试懒加载
false default即可加载创建对象
true 懒加载
*/
public class TestSpring4 {
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
//Object p2 = applicationContext.getBean("p2");
//System.out.println(p2);
}
}
spring的DI概述与应用
依赖注入DI的定义:spring创建对象的过程中,将对象依赖的属性通过配置赋值给该对象
方式:Setter注入又称之为属性注入、构造器注入、注解方式注入
1、Setter注入讲解:
package com.wolfcode.test.Spring5;
public class Person3 {
private Integer id;
private String name;
public void setId(Integer id){
this.id = id;
}
public Integer getId(){
return this.id;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return this.name;
}
@Override
public String toString() {
return "Person3{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
<bean id="p3" class="com.wolfcode.test.Spring5.Person3">
<property name="id" value="123"></property>
<property name="name" value="李四"></property>
</bean>
package com.wolfcode.test.Spring5;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5 {
//传统方式
@Test
public void test1(){
Person3 person3 = new Person3();
person3.setId(1);
person3.setName("张三");
System.out.println(person3.getId()+"--"+person3.getName());
}
//使用spring方式中setter方式赋值
@Test
public void test2(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Person3 p3 = (Person3)applicationContext.getBean("p3");
System.out.println(p3);
}
}
spring中的bean标签中的property name 属性值与类型中的setter方法名称匹配,并不是与类中的属性匹配
value只能对基本类型进行标注
<property name="id" value="123"></property>
<property name="name" value="李四"></property>
注入属性对象和注入属性普通值不太一样:
a.注入属性普通值使用value
b.注入属性对象时,需要容器中存在该对象(bean),无先后顺序之分
<bean id="h1" class="com.wolfcode.test.Spring5.Hobby">
<property name="hid" value="101"></property>
<property name="hname" value="学习"></property>
<property name="hdesc" value="除了学习之外爱好还是学习"></property>
</bean>
<bean id="p3" class="com.wolfcode.test.Spring5.Person3">
<property name="id" value="123"></property>
<property name="name" value="李四"></property>
<property name="hobby" ref="h1"></property>
</bean>
package com.wolfcode.test.Spring6;
import com.wolfcode.test.Spring5.Person3;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring6 {
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
Person3 p3 = applicationContext.getBean("p3", Person3.class);
System.out.println(p3);
}
}
2、构造器注入
–如果类型中存在某一个有参数的构造方法,那么在bean标签中就需要设置对应的参数个数以及类型
<bean id="h2" class="com.wolfcode.test.Spring5.Hobby">
<property name="hid" value="102"></property>
<property name="hname" value="照镜子"></property>
<property name="hdesc" value="一直照镜子"></property>
</bean>
<bean id="p3" class="com.wolfcode.test.Spring5.Person3">
<constructor-arg name="id" value="10001"></constructor-arg>
<constructor-arg name="name" value="西施"></constructor-arg>
<constructor-arg name="hobby" ref="h2"></constructor-arg>
</bean>
package com.wolfcode.test.Spring5;
public class Person3 {
private Integer id;
private String name;
private Hobby hobby;
private Person3(){}
public Person3(Integer id, String name, Hobby hobby) {
this.id = id;
this.name = name;
this.hobby = hobby;
}
public Hobby getHobby() {
return hobby;
}
public void setHobby(Hobby hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
return "Person3{" +
"id=" + id +
", name='" + name + '\'' +
", hobby=" + hobby +
'}';
}
}
拓展
代码后期–分层:控制层(controler)、业务层(service)、持久层(dao)–之间的依赖关系
循环依赖问题
setter方式注入测试
<bean id="a" class="com.wolfcode.test.Spring6.A">
<property name="aname" value="a类型"></property>
<property name="b" ref="b" ></property>
</bean>
<bean id="b" class="com.wolfcode.test.Spring6.B">
<property name="bname" value="b类型"></property>
<property name="c" ref="c"></property>
</bean>
<bean id="c" class="com.wolfcode.test.Spring6.C">
<property name="cname" value="c类型"></property>
<property name="a" ref="a"></property>
</bean>
public class TestSpring6 {
//循环依赖--setter方式注入测试
//循环依赖--构造器方式注入测试->出现报错
@Test
public void test2(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
A a = applicationContext.getBean("a",A.class);
System.out.println(a);
B b = applicationContext.getBean("b",B.class);
System.out.println(b);
C c = applicationContext.getBean("c",C.class);
System.out.println(c);
}
}
没有出现报错,成功执行
如果使用构造器注入的方式会出现报错
如何将jdbc如何应用在spring框架中?
思路:因为connection是由DriverManager创建的,把DriverManager交给spring容器管理,我们只需要从容其中获取到DriverManager的对象,然后从该对象中获取到connection链接对象
实现:
/**
* 测试spring-jdbc提供的DriverManagaerDataSource
*/
@Test
public void test4() throws SQLException {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
DriverManagerDataSource dataSource = ac.getBean("dataSource", DriverManagerDataSource.class);
System.out.println(dataSource);
Connection connection = dataSource.getConnection();
System.out.println(connection);
//使用完成后依然要关闭链接
}
/**
* 测试自己将jdbc整合到spring容器中
*/
//该方法不推荐,好像是wile使用spring而使用spring,太麻烦。
@Test
public void test3() throws SQLException {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
DriverManager driverManager = ac.getBean("driverManager", DriverManager.class);
System.out.println(driverManager);
Connection conn = driverManager.getConnection("jdbc:mysql://localhost:3306/test_1", "root", "123456");
System.out.println(conn);
}
jdbcTemplate
1.首先用ClassPathXmlApplicationContext类建立与spring容器配置文件beans.xml之间的联系。
2.通过JdbcTemplate类创建相关对象,从beans.xml中获取对象类型
3.使用JdbcTemplate中自带的成员方法进行数据库操作
(相比传统方式不需要Connection)
/**
* 聚合查询测试
*/
@Test
public void test8(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
Integer count = jdbcTemplate.queryForObject("select count(*) from t_user", Integer.class);
System.out.println(count);
}
/**
* 将结果集封装到对象中测试
*/
@Test
public void test7(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
String sql="select * from t_user where uid=?" ;
List<T_User> queryResult = jdbcTemplate.query(sql, new RowMapper<T_User>() {
@Override
public T_User mapRow(ResultSet rs, int rowNum) throws SQLException {
T_User t_user = new T_User();
t_user.setUid(rs.getInt("uid"));
t_user.setRid(rs.getInt("rid"));
t_user.setUidcard(rs.getString("uidcard"));
t_user.setUname(rs.getString("uname"));
t_user.setUphone(rs.getString("uphone"));
return t_user ;
}
},1);
//遍历打印
for(T_User user:queryResult){
System.out.println(user);
}
}
/**
* 多条结果集查询
*/
@Test
public void test6(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
String sql="select * from t_user" ;
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
for (Map<String,Object> map:list) {
System.out.println(map);
}
}
/**
* 测试jdbcTemplate-测试获取数据 --只能支持单条数据查询
*/
@Test
public void test5(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
Map<String, Object> stringObjectMap = jdbcTemplate.queryForMap("select * from t_user");
System.out.println(stringObjectMap);
}
实现增删改功能(基于本地mysql中student表)
@Test
public void delAccount(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
String sql="delete from Student where Sno='201215121'";
int count = jdbcTemplate.update(sql);
if (count>0){
System.out.println("删除成功");
}
}
@Test
public void addAccount(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
String sql="insert into Student(Sno,Sname,Ssex,Sage,Sdept) values('202115126','guozhao','m',18,'CS')";
int count = jdbcTemplate.update(sql);
if (count>0){
System.out.println("添加成功");
}
}
@Test
public void updaAcccount(){
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
String sql="update Student set Sage=20 where Sno='201215123'";
int count = jdbcTemplate.update(sql);
if (count>0){
System.out.println("修改成功");
}
}
连接池的技术
概念以及作用:为数据库创建一个缓冲池,预先在池子中存放一定数量的链接(connection),当我们需要使用链接的时候,直接从缓冲池中获取到链接,直接使用。结束的时候,链接会被缓冲池进行回收,从而避免了平凡的向数据库申请资源(链接)。
节省了资源,提高了响应速度,统一管理链接,避免数据库链接的泄露。
DBCP连接池:
1.导入commons-dbcp2-jar与commons-pool2-jar架包
2.配置beans.xml文件:
<bean id="basicDataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="maxTotal" value="20"></property>
</bean>
3.测试代码:
@Test
public void test9() throws SQLException {
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
BasicDataSource basicDataSource = ac.getBean("basicDataSource", BasicDataSource.class);
Connection connection = basicDataSource.getConnection();
System.out.println(connection);
}
BasicDataSource—配置beans.xml中赋值四大参数
Druid连接池:
1.导入druid架包
2.配置beans.xml文件
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${jdbc.url}"></property>
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="maxActive" value="20"></property>
</bean>
3.测试代码
spring注册小案例
分controller service dao三层
N_User(工具类)
package com.wolfcode.test.test8.Dao.entity;
import java.lang.Integer;
import java.lang.String;
public class N_User {
private Integer uid;
private String uname;
private String uphone;
private String uidcard;
private Integer rid;
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUphone() {
return uphone;
}
public void setUphone(String uphone) {
this.uphone = uphone;
}
public String getUidcard() {
return uidcard;
}
public void setUidcard(String uidcard) {
this.uidcard = uidcard;
}
public Integer getRid() {
return rid;
}
public void setRid(Integer rid) {
this.rid = rid;
}
@Override
public String toString() {
return "N_User{" +
"uid=" + uid +
", uname='" + uname + '\'' +
", uphone='" + uphone + '\'' +
", uidcard='" + uidcard + '\'' +
", rid=" + rid +
'}';
}
}
UserDao(接口类)
package com.wolfcode.test.test8.Dao.Dao;
import com.wolfcode.test.test8.Dao.entity.N_User;
//用户相关的持久层的接口
public interface UserDao {
//定义了一个方法插入用户
void insert(N_User user);
}
UserDaoImpl(dao层实现类)
package com.wolfcode.test.test8.Dao.Dao.impl;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.wolfcode.test.test8.Dao.Dao.UserDao;
import com.wolfcode.test.test8.Dao.entity.N_User;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class UserDaoImpl implements UserDao {
private DruidDataSource druidDataSource;
public void setDruidDataSource(DruidDataSource druidDataSource){
this.druidDataSource = druidDataSource;
}
@Override
public void insert(N_User user) {
DruidPooledConnection connection = null;
try {
connection = druidDataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("insert into t_user values(?,?,?,?,?)");
preparedStatement.setInt(1,user.getUid());
preparedStatement.setString(2,user.getUname());
preparedStatement.setString(3,user.getUidcard());
preparedStatement.setString(4,user.getUphone());
preparedStatement.setInt(5,user.getRid());
} catch (SQLException e) {
e.printStackTrace();
}
}
}
UserService(抽象类)
package com.wolfcode.test.test8.Dao.Service;
import com.wolfcode.test.test8.Dao.entity.N_User;
public interface UserService {
void addUser(N_User user);
}
UserServiceImpl(service层实现类)
package com.wolfcode.test.test8.Dao.Service.impl;
import com.wolfcode.test.test8.Dao.Dao.UserDao;
import com.wolfcode.test.test8.Dao.Service.UserService;
import com.wolfcode.test.test8.Dao.entity.N_User;
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
@Override
public void addUser(N_User user) {
//调用dao层方法
userDao.insert(user);
}
}
Test类:
package com.wolfcode.test.test8.Dao;
import com.wolfcode.test.test8.Dao.Dao.UserDao;
import com.wolfcode.test.test8.Dao.Service.UserService;
import com.wolfcode.test.test8.Dao.entity.N_User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test8 {
@Test
public void test2_UserService(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserService userService = applicationContext.getBean("userService", UserService.class);
N_User user = new N_User();
user.setUid(5);
user.setUname("tianhao");
user.setUidcard("1234");
user.setUphone("1222222");
user.setRid(6);
userService.addUser(user);
}
@Test
public void test1_UserDao(){
//获取容器
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
UserDao userDao = applicationContext.getBean("userDao", UserDao.class);
N_User user = new N_User();
user.setUid(4);
user.setUname("tiany");
user.setUidcard("123");
user.setUphone("1111111");
user.setRid(5);
userDao.insert(user);
}
}
spring的单元测试
基于上述案例
//单元测试
@RunWith(SpringJUnit4ClassRunner.class)//引用字节码文件
@ContextConfiguration("/beans.xml")
public class SpringTest {
@Autowired
private UserService userService;//注释自动从容器中创建对象并赋值
@Test
public void test1(){
System.out.println(userService);
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gI0CaDky-1681133087660)(C:\Users\FASQD\AppData\Roaming\Typora\typora-user-images\image-20220803145408231.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6F8kMoHF-1681133087661)(C:\Users\FASQD\AppData\Roaming\Typora\typora-user-images\image-20220803145542276.png)]
IOC注解之类注解
(为了解决bean文件配置繁杂问题)
@Repository --用于标注数据访问组件,dao类,dao层
@Service --用于标注业务层实现类上,service层
@Controller --控制层--web项目时经常用到
@Component --组件,工具,第三方框架
必须要在beans.xml中配置扫描器——扫描指定包中的添加了类注解的类型,spring扫描到之后可以自动的将他们转成bean
<context:component-scan base-package="com.wolfcode.test.Spring7"></context:component-scan>
两种方式:
第一种方式可以使用配置bean标签的方式,
第二种方式可以配置类注解将类型转成bean
类注解的方式也可以对对象属性进行赋值:
@Value可以修饰基本属性
@Value("张三")
private String name;
@Value("11111")
private Integer id;
@Autowired注解可以给引用类型赋值(也称为注入)
@Autowired
private Hobby hobby;
两种注解添加在属性或者属性对象上注入,并没有依赖该类中的构造方法和setter方法,这就是spring中的注解注入方式。
备注:@Value与@Autowired可以放到setter方法上,效果和上述相同。
@Autowired优先按照类型查找bean,当有多个相同类型的bean时,按照注解修饰的属性名称查找对应bean
@Qualifier(”…“)按照属性名称查找与bean中id匹配的bean
@Resource(name = “…”)首先按照修饰的属性名称查找bean,找到了就直接注入该bean;
如果按照名称查找找不到那就按照类型查找,匹配了该类型的多个bean–>报错,没有匹配到多个类型–>将单个该类型直接注入;
可以使用(name=”…“)指定要匹配的bean的名称(id),找不到–>按照名称查找–>找不到–>报错
@Resource注解来源于jdk,@Autowired注解来源于spring框架
Scope/PostConstrut/PreDestory注解
通过注释实现spring容器的使用,减少多余的bean文件配置以及文件操作步骤
scope==@Scope
init—method==@PostConstrut—创建完该对象立刻执行初始化(调用某一方法)
destory—method==@PreDestory关闭链接
案例:
不使用框架配置的方式,使用druid连接池
package com.wolfcode.test.Spring7;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.sql.Connection;
import java.sql.SQLException;
//@Scope("prototype")
@Component
public class MyDruid {
private DruidDataSource druidDataSource;
//创建连接池
public MyDruid(){
druidDataSource = new DruidDataSource();
System.out.println("连接池已被创建");
}
//初始化连接池
@PostConstruct
public void init(){
druidDataSource.setUrl("jdbc:mysql://localhost:3306/db1");
druidDataSource.setUsername("root");
druidDataSource.setPassword("root");
System.out.println("连接池已初始化");
}
//获取链接
public Connection getConnection(){
try {
return druidDataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//关闭
@PreDestroy
public void closeDruid(){
druidDataSource.close();
System.out.println("连接池已经关闭");
}
}
package com.wolfcode.test.Spring7;
import org.junit.Test;
import java.sql.Connection;
public class MyDruidTest {
@Test
public void test1(){
MyDruid myDruid = new MyDruid();
//初始化操作
myDruid.init();
Connection connection = myDruid.getConnection();
System.out.println(connection);
}
}
练习(用注释解决)
使用注解的方式配置模拟用户注册
N_Use工具类不变
添加日志记录
需求:
再插入用户信息的使用同时用户的操作记录,思路:
新增一张表–开发–步骤
新增对应实体类型
package com.wolfcode.test.test8.Dao.entity;
public class Opration {
private Integer id;
private String operation;
private Integer uid;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
@Override
public String toString() {
return "Opration{" +
"id=" + id +
", operation='" + operation + '\'' +
", uid=" + uid +
'}';
}
}
UserServiceImpl实现类:
package com.wolfcode.test.test8.Dao.Service.impl;
import com.wolfcode.test.test8.Dao.Dao.UserDao;
import com.wolfcode.test.test8.Dao.Service.UserService;
import com.wolfcode.test.test8.Dao.entity.N_User;
import com.wolfcode.test.test8.Dao.entity.Opration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
//不用再使用setter方法进行属性注入
// public void setUserDao(UserDao userDao){
// this.userDao = userDao;
// }
@Override
public void addUser(N_User user, Opration opration) {
//调用dao层方法
userDao.insert(user);
//调用dao层的方法插入一段日志信息
userDao.insertLog(opration);
}
}
UserService接口:
package com.wolfcode.test.test8.Dao.Service;
import com.wolfcode.test.test8.Dao.entity.N_User;
import com.wolfcode.test.test8.Dao.entity.Opration;
public interface UserService {
void addUser(N_User user, Opration opration);
}
UserDaoImpl实现类:
package com.wolfcode.test.test8.Dao.Dao.impl;
import com.wolfcode.test.Spring7.MyDruid;
import com.wolfcode.test.test8.Dao.Dao.UserDao;
import com.wolfcode.test.test8.Dao.entity.N_User;
import com.wolfcode.test.test8.Dao.entity.Opration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private MyDruid myDruid;
//不需要再用setter方法进行属性注入
// public void setDruidDataSource(DruidDataSource druidDataSource){
// this.druidDataSource = druidDataSource;
// }
@Override
public void insert(N_User user) {
try {
Connection connection = myDruid.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("insert into t_user values(?,?,?,?,?)");
preparedStatement.setInt(1,user.getUid());
preparedStatement.setString(2,user.getUname());
preparedStatement.setString(3,user.getUidcard());
preparedStatement.setString(4,user.getUphone());
preparedStatement.setInt(5,user.getRid());
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void insertLog(Opration opration) {
try {
Connection connection = myDruid.getConnection();
PreparedStatement pst = connection.prepareStatement("insert into t_operation(operation,uid) values (?,?)");
pst.setString(1,opration.getOperation());
pst.setInt(2,opration.getUid());
double i = 10/0;
pst.executeUpdate();
}catch (SQLException e){
e.printStackTrace();
}
}
}
UserDao接口:
package com.wolfcode.test.test8.Dao.Dao;
import com.wolfcode.test.test8.Dao.entity.N_User;
import com.wolfcode.test.test8.Dao.entity.Opration;
//用户相关的持久层的接口
public interface UserDao {
//定义了一个方法插入用户
void insert(N_User user);
//插入日志信息
void insertLog(Opration opration);
}
SpringTest测试类:
package com.wolfcode.test.test8.Dao.SpringTest;
import com.wolfcode.test.test8.Dao.Dao.UserDao;
import com.wolfcode.test.test8.Dao.Service.UserService;
import com.wolfcode.test.test8.Dao.entity.N_User;
import com.wolfcode.test.test8.Dao.entity.Opration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//单元测试
@RunWith(SpringJUnit4ClassRunner.class)//引用字节码文件
@ContextConfiguration("/beans.xml")
public class SpringTest {
@Autowired
private UserService userService;//注释自动从容器中创建对象并赋值
@Autowired
UserDao userDao;
/*@Test
public void test2(){
Opration opration = new Opration();
opration.setOperation("测试");
opration.setUid(1);
userDao.insertLog(opration);
}*/
@Test
public void test1(){
System.out.println(userService);
N_User n_user = new N_User();
n_user.setUid(9);
n_user.setUname("haohao");
n_user.setUidcard("1111212");
n_user.setUphone("1212121");
n_user.setRid(9);
//初始化
Opration opration = new Opration();
opration.setOperation("dada");
opration.setUid(6);
userDao.insertLog(opration);
userService.addUser(n_user,opration);
}
}
自定义事务管理工具类解决问题
插入日志信息时异常,但是用户信息成功插入了,要解决这个问题:
同一个链接–insertUser insertLog
Dao层–先获取链接
业务层中–commit//rollback
a.思路 b.不使用spring事务管理->自行设计事务管理工具类,来进行异常处理
MyTransManager事务管理器:
package com.wolfcode.test.test8.Dao.util;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.sql.Connection;
import java.sql.SQLException;
//事务管理器
@Component
public class MyTransManager {
@Autowired
DruidDataSource druidDataSource;
//进行保存同一个链接
//保存线程里面的静态变量
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();//泛型
//获取链接
public Connection getConnection() throws SQLException {
Connection connection = threadLocal.get();
if(connection!=null){//说明线程当中存在connection
return connection;
}
connection = druidDataSource.getConnection();
threadLocal.set(connection);
return connection;
}
//开启事务
public void startTrans() throws SQLException {
getConnection().setAutoCommit(false);
}
//提交
public void commit() throws SQLException {
getConnection().commit();
}
//回滚操作
public void roollback() throws SQLException { getConnection().rollback();
}
}
代理模式
1、静态代理模式
代码:
package com.wolfcode.test.test8.Dao.Service.impl;
import com.wolfcode.test.test8.Dao.Service.UserService;
import com.wolfcode.test.test8.Dao.entity.N_User;
import com.wolfcode.test.test8.Dao.entity.Opration;
import com.wolfcode.test.test8.Dao.util.MyTransManager;
import org.springframework.beans.factory.annotation.Autowired;
import java.sql.SQLException;
public class UserServiceImplProxy implements UserService {
@Autowired
private UserService userServiceImpl;
@Autowired
private MyTransManager myTransManager;
@Override
public void addUser(N_User user, Opration opration) {
System.out.println("执行代理类中的方法");
try {
//开启事务
myTransManager.startTrans();
//调用真实的业务实现类对象方法
userServiceImpl.addUser(user,opration);
//提交事务
myTransManager.commit();
} catch (SQLException e) {
//回滚操作
try {
myTransManager.roollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
2、动态代理模式
步骤:
首先:通过InvocationHandler接口来构建模板。
其次:重写invoke方法
1、jdk动态代理
TransInvocationHandler代理类:
package com.wolfcode.test.test8.Dao.Service.impl;
//事务管理增强的一个模板--事务管理增强的一个工具类--不是一个代理类
//作为动态代理模式中创建代理类的模板
import com.wolfcode.test.test8.Dao.util.MyTransManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
@Component
public class TransInvocationHandler implements InvocationHandler {
//引入真实的业务对象
@Autowired//不适用
@Qualifier("userServiceImpl")
private Object target;
//引入事务管理器-->需要增强的功能
@Autowired
MyTransManager myTransManager;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object value = null;
try {
myTransManager.startTrans();
value = method.invoke(target, args);//调用某一个指定对象
myTransManager.commit();
}catch (Exception e){
myTransManager.roollback();
}
return value;
}
public Object getTarget() {
return target;
}
}
测试代码:
//测试jdk动态代理
@Test
public void test1(){
//生成代理类
//使用反射机制
//第一个参数:真实业务对象对应类型的类加载器
//第二个参数:真实业务对象对应的真实业务实现的接口
//第三个参数:模板-就是告诉jdk需要生成的代理类时干什么的(事务怎强)
UserServiceImpl userService = (UserServiceImpl) Proxy.newProxyInstance(transInvocationHandler.getTarget().getClass().getClassLoader(),
transInvocationHandler.getTarget().getClass().getInterfaces(),
transInvocationHandler);
//实则是调用了生成的代理类对象的addUser方法(进行了事务增强之后的)
N_User n_user = new N_User();
n_user.setUid(1);
n_user.setUname("abc");
n_user.setUidcard("11111122");
n_user.setUphone("121211111");
n_user.setRid(1);
//初始化
Opration opration = new Opration();
opration.setOperation("ikun");
opration.setUid(1);
opration.setId(1);
// userDao.insertLog(opration);
userService.addUser(n_user,opration);
}
2、CGlib动态代理
TransInvocationHandler_cglib代理类:
package com.wolfcode.test.test8.Dao.Service.impl;
import com.wolfcode.test.test8.Dao.util.MyTransManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
//导包一定要正确不要与jdk动态代理搞混
import org.springframework.cglib.proxy.InvocationHandler;
import java.lang.reflect.Method;
@Component("transInvocationHandler_cglib")
public class TransInvocationHandler_cglib implements InvocationHandler {
@Autowired
@Qualifier("userServiceImpl")
private Object target;
public Object getTarget() {
return target;
}
//引入跟事务相关的事务管理器
@Autowired
MyTransManager myTransManager;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//先声明一个返回值
Object value = null;
try {
myTransManager.startTrans();
value = method.invoke(target, args);
myTransManager.commit();
}catch (Exception e){
myTransManager.roollback();
}
return value;
}
}
测试代码:
//测试使用cglib动态代理
@Test
public void test2(){
System.out.println("执行cglib动态代理测试");
//spring框架提供了一个Enhancer类型
Enhancer enhancer = new Enhancer();
//使用该对象设置相关的属性
//设置生成的代理类继承的类--设置业务类-类型
enhancer.setSuperclass(transInvocationHandler_cglib.getTarget().getClass());
//设置代理类需要做什么事(体现在TransInvocationHandler_cglib)
enhancer.setCallback(transInvocationHandler_cglib);
//就是根据当前的设置创建-代理类-(代理类的对象)
//使用接口接收
//UserService userService = (UserService) enhancer.create();
//使用实现类接收
UserServiceImpl userService = (UserServiceImpl)enhancer.create();
System.out.println(userService);
//可以调用userService中的方法
N_User user = new N_User();
user.setUid(11);
user.setUname("xiaoming");
user.setUidcard("888888");
user.setUphone("1112121212");
user.setRid(11);
Opration opration = new Opration();
opration.setOperation("insertuser");
opration.setUid(2);
// userDao.insertLog(opration);
userService.addUser(user,opration);
}
enhancer.create()创建的对象可以通过接口类型强转或者是通过真实的业务实现类强转,cglib动态代理生成的类型是真实业务类的子类
3、二者对比:
jdk动态代理中,创建的代理类,实际上是真实业务类实现的接口的另一个实现,所以说只能通过接口进行强转,不能够通过真实业务类进行强转。
cglib动态代理,它的使用更加自由,不想jdk动态代理(必须要业务实现类实现接口),cglib动态代理可以不用实现任何接口。
4、SpringTest3完整代码,包含jdk测试与cglib测试:
package com.wolfcode.test.test8.Dao.SpringTest;
//测试动态代理
import com.wolfcode.test.test8.Dao.Service.impl.TransInvocationHandler;
import com.wolfcode.test.test8.Dao.Service.impl.TransInvocationHandler_cglib;
import com.wolfcode.test.test8.Dao.Service.impl.UserServiceImpl;
import com.wolfcode.test.test8.Dao.entity.N_User;
import com.wolfcode.test.test8.Dao.entity.Opration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.lang.reflect.Proxy;
//单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/beans.xml")
public class SpringTest3 {
// @Autowired
// private UserService userService;
@Autowired
TransInvocationHandler_cglib transInvocationHandler_cglib;
// @Autowired
// UserDao userDao;
@Autowired
TransInvocationHandler transInvocationHandler;
//测试使用cglib动态代理
@Test
public void test2(){
System.out.println("执行cglib动态代理测试");
//spring框架提供了一个Enhancer类型
Enhancer enhancer = new Enhancer();
//使用该对象设置相关的属性
//设置生成的代理类继承的类--设置业务类-类型
enhancer.setSuperclass(transInvocationHandler_cglib.getTarget().getClass());
//设置代理类需要做什么事(体现在TransInvocationHandler_cglib)
enhancer.setCallback(transInvocationHandler_cglib);
//就是根据当前的设置创建-代理类-(代理类的对象)
//使用接口接收
//UserService userService = (UserService) enhancer.create();
//使用实现类接收
UserServiceImpl userService = (UserServiceImpl)enhancer.create();
System.out.println(userService);
//可以调用userService中的方法
N_User user = new N_User();
user.setUid(11);
user.setUname("xiaoming");
user.setUidcard("888888");
user.setUphone("1112121212");
user.setRid(11);
Opration opration = new Opration();
opration.setOperation("insertuser");
opration.setUid(2);
// userDao.insertLog(opration);
userService.addUser(user,opration);
}
//测试jdk动态代理
@Test
public void test1(){
//生成代理类
//使用反射机制
//第一个参数:真实业务对象对应类型的类加载器
//第二个参数:真实业务对象对应的真实业务实现的接口
//第三个参数:模板-就是告诉jdk需要生成的代理类时干什么的(事务怎强)
UserServiceImpl userService = (UserServiceImpl) Proxy.newProxyInstance(transInvocationHandler.getTarget().getClass().getClassLoader(),
transInvocationHandler.getTarget().getClass().getInterfaces(),
transInvocationHandler);
//实则是调用了生成的代理类对象的addUser方法(进行了事务增强之后的)
N_User n_user = new N_User();
n_user.setUid(1);
n_user.setUname("abc");
n_user.setUidcard("11111122");
n_user.setUphone("121211111");
n_user.setRid(1);
//初始化
Opration opration = new Opration();
opration.setOperation("ikun");
opration.setUid(1);
opration.setId(1);
// userDao.insertLog(opration);
userService.addUser(n_user,opration);
}
}
aop(同样可以通过注解实现)
什么叫aop?
面向切面编程技术,把每一个关注点放到模块中,产生了切面的概念,每一个切面相当于是一个增强的功能方法。aop主要是应用在日志记录,权限检查、事务控制、异常处理、性能统计
专业术语:
连接点:joinpoint:指被增强的方法(业务类)
切入点:pointCut:指连接点的集合(多个链接点)
切面:aspect:增强的功能的方法(事务管理器–>开启事务、提交、回滚)
植入:把切面加到切入点,创建新的代理对象的过程。
aop的实现补充:(为什么要导入aspectj)
aop联盟制定的aop规范。spring框架率先实现了aop思想-spring框架整合了一个新的框架AspectJ(切入点表达式)–>spring-aop更加便捷,使用spring-aop需要导入aspectj相关jar包
实现过程:
1、首先导入spring-aop.jar以及asjectj相关架包
2、配置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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--加载到jdbc.properties-->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<!--设置druid连接池-->
<!--<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">-->
<!--<property name="url" value="${jdbc.url}"></property>-->
<!--<property name="driverClassName" value="${jdbc.driverClassName}"></property>-->
<!--<property name="username" value="${jdbc.username}"></property>-->
<!--<property name="password" value="${jdbc.password}"></property>-->
<!--<property name="maxActive" value="20"></property>-->
<!--</bean>-->
<!--添加扫描器-->
<context:component-scan base-package="com.wolfcode.test.Spring8"></context:component-scan>
<context:component-scan base-package="com.wolfcode.test.*"></context:component-scan>
<!--<!–aop配置–>-->
<!--<aop:config>-->
<!--<!–定义切面-表示增强的功能–>-->
<!--<aop:aspect ref="myTransManager" order="2">-->
<!--<!–定义切点,表示该切面在那些地方执行功能增强–>-->
<!--<aop:pointcut id="p1" expression="execution(* com.wolfcode.test.Spring8.Service.impl.UserServiceImpl.addUser(..))"></aop:pointcut>-->
<!--<!–在执行切点方法之前先做什么事情–>-->
<!--<aop:before method="startTrans" pointcut-ref="p1"></aop:before>-->
<!--<!–在方法成功执行时–>-->
<!--<aop:after-returning method="commit" pointcut-ref="p1"></aop:after-returning>-->
<!--<!–在方法执行时出现异常–>-->
<!--<aop:after-throwing method="roollback" pointcut-ref="p1"></aop:after-throwing>-->
<!--</aop:aspect>-->
<!--<!–定义计算耗时的切面–>-->
<!--<aop:aspect ref="computeTime" order="0">-->
<!--<aop:pointcut id="p2" expression="execution(* com.wolfcode.test.Spring8.Service.impl.UserServiceImpl.addUser(..))"></aop:pointcut>-->
<!--<aop:before method="getStartTime" pointcut-ref="p2"></aop:before>-->
<!--<aop:after-returning method="getEndTime" pointcut-ref="p2"></aop:after-returning>-->
<!--<aop:after-throwing method="getEndTime" pointcut-ref="p2"></aop:after-throwing>-->
<!--</aop:aspect>-->
<!--</aop:config>-->
<!--需要配置一个让aop注解生效的配置-->
<aop:aspectj-autoproxy />
</beans>
package com.wolfcode.test.Spring8.util2;
//计算耗时
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//获取起始的时间戳
//获取终止的时间戳
@Component
@Aspect
public class ComputeTime {
private Long startTime;
@Pointcut("execution(* com.wolfcode.test.Spring8.Service.impl.UserServiceImpl.addUser(..))")
public void pointCut(){
}
@Before("pointCut()")
public void getStartTime(){
startTime = System.currentTimeMillis();
System.out.println("获取到开始时间戳");
}
@AfterThrowing("pointCut()")
// @AfterRunning("pointCut()")
public void getEndTime(){
long endTime = System.currentTimeMillis();
//做差打印出耗时
System.out.println("获取到结束时间戳");
System.out.println("计算耗时:"+(endTime-startTime)+"ms");
}
}
ORM持久层框架
orm概念?
对象关系映射,解决面向对象与关系数据库存在的互不匹配的现象的技术
orm的映射方式:
把sql配置在sql文件中,通过不同的sql完成对象实体与数据库关系的相互转换
orm的好处?
1、把实体模型和数据库表映射
2、orm框架启动加载映射和数据库配置文件
3、orm对原生的jdbc封装提供了更多的api
4、持久层通过orm提供的便捷的api以对象的方式操作数据库更加便捷
mybatis
mybatis概念:orm的数据库持久层框架
内存中的数据保存到磁盘或者数据库中
1、导入jar包
2、新建包
实现一个需求:使用mybatis的方式去实现CRUD
3、新增dao包,dao接口以及接口实现类
问题:mybatis给我们提供了一个sqlSession
配置文件xml
mybatis_config.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--加载jdbc参数的配置文件 -->
<properties resource="jdbc.properties"></properties>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!--mybatis剥离出的sql文件 -->
<mappers>
<mapper resource="com/wolfcode/mybatis_test/mapper/UserMapper.xml"></mapper>
</mappers>
</configuration>
UserMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wolfcode.test.mybatis_test.dao.UserDao">
<insert id="insert" parameterType="com.wolfcode.test.mybatis_test.entity.T_user">
insert into t_user values(#{uid},#{uname},#{uphone},#{uidcard},#{rid})
</insert>
<update id="update" parameterType="com.wolfcode.test.mybatis_test.entity.T_user">
update t_user
<trim prefix="set" suffixOverrides=",">
<if test="uname !=null and uname!=''">
uname=#{uname},
</if>
<if test="uphone !=null and uphone!=''">
uphone=#{uphone},
</if>
<if test="uidcard !=null and uidcard!=''">
uidcard=#{uidcard},
</if>
<if test="rid != null">
rid=#{rid},
</if>
</trim>
<if test="uid !=null">
where uid=#{uid}
</if>
</update>
<delete id="delete" parameterType="java.lang.Integer">
delete from t_user where uid=#{uid}
</delete>
<select id="selectSingle" parameterType="java.lang.Integer" resultType="com.wolfcode.test.mybatis_test.entity.T_user">
select * from t_user where uid=#{uid}
</select>
<select id="selectUserList" parameterType="java.util.Map" resultType="com.wolfcode.test.mybatis_test.entity.T_user">
select * from t_user
<where>
<if test="uname !=null">
uname=#{uname}
</if>
<if test="uphone !=null">
or uphone=#{uphone}
</if>
</where>
</select>
</mapper>
持久层:
UserDaoImpl:
package com.wolfcode.test.mybatis_test.dao.impl;
//持久层实现类
import com.wolfcode.test.mybatis_test.dao.UserDao;
import com.wolfcode.test.mybatis_test.entity.T_user;
import com.wolfcode.test.mybatis_test.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
import java.util.Map;
public class UserDaoImpl implements UserDao {
@Override
public void insert(T_user user) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
// Connection connection = sqlSession.getConnection();//保留传统方式
// PreparedStatement preparedStatement = connection.prepareStatement();
// try {
// connection.setAutoCommit(true);
// } catch (SQLException e) {
// e.printStackTrace();
// }
int insert = sqlSession.insert("com.wolfcode.test.mybatis_config.dao.UserDao.insert", user);
System.out.println(insert);
}
@Override
public void update(T_user user) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
sqlSession.update("com.wolfcode.test.mybatis_config.dao.UserDao.update", user);
}
@Override
public void delete(Integer uid) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
sqlSession.delete("com.wolfcode.test.mybatis_config.dao.UserDao.delete", uid);
}
@Override
public List<T_user> selectUserList(Map<String, Object> paramMap) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
return sqlSession.selectList("com.wolfcode.test.mybatis_test.dao.UserDao.selectUserList", paramMap);
}
@Override
public T_user selectSingle(Integer uid) {
SqlSession sqlSession = MyBatisUtil.getSqlSession();
return sqlSession.selectOne("com.wolfcode.test.mybatis_config.dao.UserDao.selectSingle", uid);
}
}
UserDao接口:
package com.wolfcode.test.mybatis_test.dao;
import com.wolfcode.test.mybatis_test.entity.T_user;
import java.util.List;
import java.util.Map;
//用户持久层接口
public interface UserDao {
//插入用户
void insert(T_user user);
//修改用户
void update(T_user user);
//删除用户
void delete(Integer uid);
//多条记录查询
List<T_user> selectUserList(Map<String,Object> paramMap);
//单条查询
T_user selectSingle(Integer uid);
}
MyBatisUtil(mybatis工具类);
package com.wolfcode.test.mybatis_test.util;
//提供sqlSession的方法
//SqlSession来源于SqlSessionFactory
//SqlSessFactory又是通过SqlSessionFactory构建
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class MyBatisUtil {
//先要声明一个SqlSessionFactory
static SqlSessionFactory sqlSessionFactory;
//通过静态代码块为sqlSessionFactory赋值
static{
try{
//创建一个sqlSessionFactory工具
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//先要加载到我们核心的配置文件InputStream
InputStream stream = Resources.getResourceAsStream("mybatis_config.xml");
sqlSessionFactory = sqlSessionFactoryBuilder.build(stream);
}catch (Exception e){
e.printStackTrace();
}
}
//获取sqlSession
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
}
测试类:
package com.wolfcode.test.mybatis_test.test;
import com.wolfcode.test.mybatis_test.entity.T_user;
import com.wolfcode.test.mybatis_test.dao.impl.UserDaoImpl;
import com.wolfcode.test.mybatis_test.dao.UserDao;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyTest {
@Test
public void test5_userDao_selectUserList(){
UserDao userDao = new UserDaoImpl();
Map<String,Object> paramMap=new HashMap<String,Object>() ;
//paramMap.put("uname","凯");
paramMap.put("uphone","321");
List<T_user> t_users = userDao.selectUserList(paramMap);
for(T_user user:t_users){
System.out.println(user);
}
}
/**
* 测试单条用户查询
*/
@Test
public void test4_userDao_selectSingle(){
UserDao userDao = new UserDaoImpl();
T_user t_user = userDao.selectSingle(1);
System.out.println(t_user);
}
/**
* 删除测试
*/
@Test
public void test3_userDao_delete(){
UserDao userDao = new UserDaoImpl();
userDao.delete(21);
}
@Test
public void test2_UserDao_update(){
UserDao userDao = new UserDaoImpl();
T_user t_user = new T_user();
t_user.setUname("tom");
userDao.update(t_user);
}
//测试UserDao插入
@Test
public void test1_UserDao_insert(){
UserDao userDao = new UserDaoImpl();
T_user user = new T_user();
user.setUid(21);
user.setUname("jerry");
user.setUidcard("1281629");
user.setUphone("1291201");
user.setRid(7);
userDao.insert(user);
}
}
springmvc
springmvc是一个基于mvc模式的web框架,springmvc是spring中的一个模块,可以和spring框架无缝集成。
mvc:model(模型)–view(视图)–controller(控制层)
1、springmvc的入门理论:
使用springmvc必须先要保证有spring环境,而且要保证spring ioc容器初始化。springmvc应用必须要导入spring相关的核心jar包
springmvc和核心jar包:
spring-webmvc、spring-web
2、springmvc的核心控制器/前端控制器
作用:主要是用来拦截请求,根据相关的规则分发请求到目标处理器
3、核心流程图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JfHYYlXk-1681133087662)(C:\Users\FASQD\AppData\Roaming\Typora\typora-user-images\image-20220808095710982.png)]
1.浏览器端(客户端)发起了一个请求,请求服务端,通过Ip:port进入到程序中-DispatcherServlet
2.DispatcherServlet携带该请求去HandlerMapping中查找对应的处理器(判断该请求对应的处理器是否存在,如果存在返回对应的处理器handler/Controller ,如果不存在则提示 404)
3.返回的过程)(写到步骤2中)
4.DispatcherServlet拿到handler去找到HanderAdatpter(处理器适配器)进行具体的执行
5.HandlerAdatpter返回一个modelAndView(数据/页面)
6.DispatcherServlet去视图解析器(ViewResolver)中,解析ModelAndView
7.ViewResolver返回一个具体的view(视图)
8.DispatcherServlet进行了一个渲染然后返回给客户端(浏览器端)
4、实际操作springmvc
1.导包 (spring框架的jar /springmvcjar)
-
按照使用spring框架的过程,在src(类路径下添加一个applicationContext.xml)
-
在web.xml中进行配置(核心控制器) --配置核心控制器过程实际上就是配置一个servlet
同时,DispatcherServlet --所有的请求都会进来 (???)
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframwork...DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>springmvc<servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
4.写了一个Handler(处理器) —第一种实现方式
public class firstHandler implements Controller{ public ModelAndView requestHandle(HttpServletRequest req,HttpServletResponse resp){ //打印是否进入到了该handler中 return null ; } }
5.进行测试 —一系列的测试
a 文件找不到的异常 (WEB-INF/firstHandler-config.xml)
b. 解析文件异常 (xml是springmvc使用的-必须要满足springmvc的规则-标签)
c. 404 --找不到对应的资源
6.存在的弊端
a.核心配置文件 (src目录下applicationContext.xml ,springmvc去web-inf查找)
对核心配置文件位置进行了优化(规范处理)。告诉DispatcherServlet初始化的时候,我给你指定一个参数 ,contextConfigLocation — classpath:applicationContext.xml ,怎么配置(使用servlet初始化参数配置 init-param param-name param-value)
b. 启动的时候,在第一次访问的时候 ,出现了一个现象 – 浏览器端一致在等待,等待了很长一段时间 ,对用户而言,体验不好 (太耗时) ----启动参数配置 (stat-load-on)
c.按照目前的写法 ,每次在写了一个处理器后,都需要配置 bean ,使用注解的方式 实现
5、注解实现
@Controller//需要controller生效 需要额外配置扫描器 public class SecondHandler{ @RequestMapping("/test.do") public ModelAndView reqeustHandle(){ //打印 } }
json
1、返回值格式
{
"name":"zhangsan",
"id":"123"
}
2、如何在程序中返回json数据
Map集合可以转换成json格式
person类型对象可以转换成json格式
//Map集合
Map<String,Object> paramMap = new HashMap<String, Object>();
paramMap.put("key","value");
paramMap.put("name","zhangsan");
Person person = new Person();
person.setId(10);
person.setName("lisi");
try{
String string = objectMapper.writeValueAsString(paramMap);
System.out.println(string);
}catch (Exception e){
e.printStackTrace();
}
@RequestMapping(“/getjson.do”)不符合restful风格(例如/user/getuser /dept/delete/test) -->添加了.do后缀或者添加了.action不符合restful风格
3、通用乱码解决方案
/**
* 接收post请求
* 1.form表单中action属性值../相对路径,解决了404问题
* 2.使用处理器可以接收到post请求
* 3.接收到post请求出现了乱码
* 4.乱码问题怎么解决?
* 回顾之前的get请求并没有出现乱码情况
* 现在post请求为什么就出现乱码了?
* 5.get请求实际上也出现了乱码只是被tomcat8.0+解决了 tomcat8一下版本没有解决
* 6.如果项目上要求使用tomcat 7 ,get请求的乱码无法解决了嘛?
* 怎么解决?在tomcat 7中添加了URIEncoding="utf-8"
* 7.post请求乱码怎么办?springmvc提供了解决方案
* 8.通用的乱码解决方案(get/post)
*
* @param uname
* @param uage
* @return
*/
@ResponseBody
@RequestMapping("/request4")
public Map<String,Object> requestHandle4(@RequestParam(value = "uname")String uname,
@RequestParam(value="uage")Integer uage){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//直接从请求参数中获取并打印
System.out.println("接收到的数据:"+uname+"---"+uage);
//将接收到的乱码的数据进行转换
try {
byte[] bytes = uname.getBytes("ISO-8859-1");
//将字节数组进行重新编码
String str=new String(bytes,"utf-8") ;
System.out.println("转码之后的字符串:"+str);
resultMap.put("name",str);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
4、相关代码
package cn.wolfcode.handler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/*8
接收参数测试
*/
@Controller
public class FiveController {
/**
* 传统方式接收参数
* @param req
* @param resp
* @return
*/
@ResponseBody
@RequestMapping("/request1")
public Map<String,Object> requestHandle1(HttpServletRequest req, HttpServletResponse resp){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//从保存请求信息的对象中获取req
String name = req.getParameter("name");
//打印
System.out.println("接收到的数据:"+name);
//设置返回值
resultMap.put("data",name);
//返回
return resultMap ;
}
/**
* 使用springmvc接收简单参数类型
* 而且要求实际传参-实参数名称和际使用的参数名称一致
* 如果不一致,会导致无法接收到参数,此时会默认该值为NULL
* 注意:
* @param name
* @param age
* @return
*/
@ResponseBody
@RequestMapping("/request2")
public Map<String,Object> requestHandle2(String name,Integer age){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//直接从请求参数中获取并打印
System.out.println("接收到的数据:"+name+"---"+age);
//设置返回值
resultMap.put("name",name);
resultMap.put("age",age);
//返回
return resultMap ;
}
/**
* 接收参数参数名称和实际使用的参数名称不一致
* @RequestParam()中的属性 name=value --表示形参的别名(处理器/接口对外暴露的参数名称)
* required =true 必传 =false 非必传 默认必传 defaultValue
* @param uname
* @param uage
* @return
*/
@ResponseBody
@RequestMapping("/request3")
public Map<String,Object> requestHandle3(@RequestParam(value = "nn")String uname,
@RequestParam(value="a",required = true)Integer uage){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//直接从请求参数中获取并打印
System.out.println("接收到的数据:"+uname+"---"+uage);
//设置返回值
resultMap.put("name",uname);
resultMap.put("age",uage);
//返回
return resultMap ;
}
/**
* 接收post请求
* 1.form表单中action属性值../相对路径,解决了404问题
* 2.使用处理器可以接收到post请求
* 3.接收到post请求出现了乱码
* 4.乱码问题怎么解决?
* 回顾之前的get请求并没有出现乱码情况
* 现在post请求为什么就出现乱码了?
* 5.get请求实际上也出现了乱码只是被tomcat8.0+解决了 tomcat8一下版本没有解决
* 6.如果项目上要求使用tomcat 7 ,get请求的乱码无法解决了嘛?
* 怎么解决?在tomcat 7中添加了URIEncoding="utf-8"
* 7.post请求乱码怎么办?springmvc提供了解决方案
* 8.通用的乱码解决方案(get/post)
*
* @param uname
* @param uage
* @return
*/
@ResponseBody
@RequestMapping("/request4")
public Map<String,Object> requestHandle4(@RequestParam(value = "uname")String uname,
@RequestParam(value="uage")Integer uage){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//直接从请求参数中获取并打印
System.out.println("接收到的数据:"+uname+"---"+uage);
//将接收到的乱码的数据进行转换
try {
byte[] bytes = uname.getBytes("ISO-8859-1");
//将字节数组进行重新编码
String str=new String(bytes,"utf-8") ;
System.out.println("转码之后的字符串:"+str);
resultMap.put("name",str);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//设置返回值
resultMap.put("age",uage);
//返回
return resultMap ;
}
@ResponseBody
@RequestMapping("/request5")
public Map<String,Object> requestHandle5(@RequestParam(value = "hobby")String[] hobby){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//打印接收到的参数
System.out.println(Arrays.toString(hobby));
//设置返回值
resultMap.put("code",9999);
//返回
return resultMap ;
}
}
需求实现:
1、接受一个人的信息(注册)
@ResponseBody
@RequestMapping("/request6")
public Map<String,Object> requestHandle6(String uname,Integer uage,String idcard,String uphone){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//打印接收到的参数
System.out.println(uname+"--"+uage+"--"+idcard+"--"+uphone);
//设置返回值
resultMap.put("code",9999);
//返回
return resultMap ;
}
备注:以上接收参数太麻烦,可以改为下面的方法
@ResponseBody
@RequestMapping("/request6")
public Map<String,Object> requestHandle6(UserInfo userInfo){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//打印接收到的参数
System.out.println(userInfo);
//设置返回值
resultMap.put("code",9999);
//返回
return resultMap ;
}
直接使用一个工具类接收参数。
备注:@RequestParam注解不能应用于实体类中。
使用实体类接受post请求中的参数也是可行的
如果使用字符类型接收–该数值且是中文,一定不能出现乱码
2、时间类型参数接收
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
3、数据回显
直接在浏览器回显数据
@RequestMapping("/request6")
public String requestHandle6(UserInfo userInfo){
//先存放用于保存键值对的map集合
Map<String,Object> resultMap=new HashMap<String,Object>() ;
//打印接收到的参数
System.out.println(userInfo);
Date birthday = userInfo.getBirthday();
//设置返回值
resultMap.put("code",9999);
//返回
return "jsp/fj.jsp" ;
}
<hr/>
<form method="get" action="../request6">
姓名:<input type="text" name="uname"/>
年龄:<input type="text" name="uage"/>
身份证:<input type="text" name="idcard"/>
手机号:<input type="text" name="uphone"/>
<input type="submit" value="提交" />
</form>
<hr/>
<h2>${userInfo.uname}</h2>
<h2>${userInfo.idcard}</h2>
<h2>${userInfo.uphone}</h2>
<h2>${userInfo.birthday}</h2
</body>
4、文件上传
传统:在servlet中实现文件上传从request中获取流
spring:springmvc实现文件上传
实际操作:
IO流:读数据写数据的过程
导入jar包
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UO693cQB-1681133087663)(C:\Users\FASQD\AppData\Roaming\Typora\typora-user-images\image-20220810110603797.png)]
第一种方式:
package cn.wolfcode.handler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//文件操作
@Controller
public class FileController {
@ResponseBody
@RequestMapping("/uploadfile")
public Map<String,Object> uploadfile(HttpServletRequest request, HttpServletResponse response){
//定义map集合
Map<String,Object> map = new HashMap<>();
ServletInputStream inputStream =null;
OutputStream outputStream = null;
try {
inputStream = request.getInputStream();
outputStream = new FileOutputStream(new File("D:\\ssm\\uploadDir\\xx.jpg"));
//定义一个byte数组
byte[] b = new byte[1024];
//读取到的长度
int len = 0;
//判断 如果read为-1那么表示数据读取完成
while((len = inputStream.read(b))!=-1){
//写的过程
String s = new String(b,"utf-8");
System.out.println(s);
outputStream.write(b,0,len);
}
//关闭流
outputStream.close();
inputStream.close();
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
map.put("code","success");
return map;
}
<hr/>
<h2>文件上传</h2>
<form action="../uploadfile" method="post" enctype="multipart/form-data">
<input type="file" name="myfile" value="选择文件"/>
<input type="submit" value="上传提交"/>
</form>
第二种方式:
@Controller
public class FileController {
@ResponseBody
@RequestMapping("/uploadfile")
public Map<String,Object> uploadfile(MultipartFile myfile){
//定义map集合
Map<String,Object> map = new HashMap<>();
try {
InputStream inputStream = myfile.getInputStream();
OutputStream outputStream = new FileOutputStream(new File("D:\\ssm\\uploadDir\\xx.jpg"));
//边读边写的过程
byte[] b = new byte[1024];
//定义长度
int len = 0;
while ((len =inputStream.read(b))!=-1){
outputStream.write(b,0,len);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
map.put("code","success");
return map;
}
}
O流:读数据写数据的过程
导入jar包
[外链图片转存中...(img-UO693cQB-1681133087663)]
第一种方式:
```java
package cn.wolfcode.handler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//文件操作
@Controller
public class FileController {
@ResponseBody
@RequestMapping("/uploadfile")
public Map<String,Object> uploadfile(HttpServletRequest request, HttpServletResponse response){
//定义map集合
Map<String,Object> map = new HashMap<>();
ServletInputStream inputStream =null;
OutputStream outputStream = null;
try {
inputStream = request.getInputStream();
outputStream = new FileOutputStream(new File("D:\\ssm\\uploadDir\\xx.jpg"));
//定义一个byte数组
byte[] b = new byte[1024];
//读取到的长度
int len = 0;
//判断 如果read为-1那么表示数据读取完成
while((len = inputStream.read(b))!=-1){
//写的过程
String s = new String(b,"utf-8");
System.out.println(s);
outputStream.write(b,0,len);
}
//关闭流
outputStream.close();
inputStream.close();
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
map.put("code","success");
return map;
}
<hr/>
<h2>文件上传</h2>
<form action="../uploadfile" method="post" enctype="multipart/form-data">
<input type="file" name="myfile" value="选择文件"/>
<input type="submit" value="上传提交"/>
</form>
第二种方式:
@Controller
public class FileController {
@ResponseBody
@RequestMapping("/uploadfile")
public Map<String,Object> uploadfile(MultipartFile myfile){
//定义map集合
Map<String,Object> map = new HashMap<>();
try {
InputStream inputStream = myfile.getInputStream();
OutputStream outputStream = new FileOutputStream(new File("D:\\ssm\\uploadDir\\xx.jpg"));
//边读边写的过程
byte[] b = new byte[1024];
//定义长度
int len = 0;
while ((len =inputStream.read(b))!=-1){
outputStream.write(b,0,len);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
map.put("code","success");
return map;
}
}