WEB课程总结

Spring

1.什么是Spring
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。

Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。
然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
目的:解决企业应用开发的复杂性
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
范围:任何Java应用

它是一个容器框架,用来装javabean(java对象),中间层框架(万能胶)可以起一个连接作用,比如说把Struts和hibernate粘合在一起运用。简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

  1. 什么是控制反转(或依赖注入)
    控制反转(IoC=Inversion of Control)IoC,用白话来讲,就是由容器控制程序之间的(依赖)关系,而非传统实现中,由程序代码直接操控。这也就是所谓“控制反转”的概念所在:(依赖)控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转。

SSH和SSM的区别

个人认为:
SSH 通常指的是 Struts2 做控制器(Action)。

SSM 则指的是 SpringMVC 做控制器(controller)。

共同点:

1.Spring依赖注入DI来管理各层的组件。

2.使用面向切面编程AOP管理事物、日志、权限等。

不同点:

1.Struts2 和 SpringMVC 控制器(controller)控制视图和模型的交互机制的不同,

2.Struts2是Action类级别,SpringMVC是方法级别,更容易实现RESTful风格。

MVC的设计模式

  1. MVC

首先MVC是M(Model)模型,V(View)视图,C(Controller)控制器,MVC是一种分离显示业务逻辑,数据和界面的一种模式。

  1. MVC设计模式的基本流程

(1)首先通过获得用户request请求(例如:请求查看某某空间)
(2)控制器获得请求后,将用户的请求转交给Model(模型)“数据库管理员”,要求获取某某空间数据
(3)通过控制器下达的指令,Model前往数据库获得相应数据,然后反馈给控制器
(4)控制器将获得的反馈数据,转交给View(视图)“数据美化师”,根据控制器提供的数据,进行相应的美化渲染
(5)View渲染后再次反馈给控制器,再将渲染后的数据反馈给客户的请求。

3.个人理解
MVC之所以被引用,在于他独特的分离显示,模块的分工明显,且不用模块的修改,不会干扰其他模块显示和运作。

Spring MVC

1.Spring MVC是Spring生态圈WebMVC中的一部分。

Spring和SpringMVC的关系
个人理解的SpringMVC是Spring核心功能的衍生物,就像是一个房子,是需要一个核心框架核心地基,在此基础上才能有更好更多的设计和发展。

struts2和SpringMVC的比较
两者和Spring的关系就好比陌生人和表亲,SpringMVC,相对会更贴切Spring,在功能和事件的应用上能更有效地发生联动

ORM程序技术

对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。 这也同时暗示者额外的执行开销;然而,如果ORM作为一种中间件实现,则会有很多机会做优化,而这些在手写的持久层并不存在。 更重要的是用于控制转换的元数据需要提供和管理;但是同样,这些花费要比维护手写的方案要少.

MyBatis

MyBatis 本是 apache 的一个开源项目 iBatis , 2010年这个项目由 apache software foundation 迁移到了 google code,并且改名为 MyBatis 。
MyBatis 的主要思想是将程序中的大量 SQL 语句抽取出来,配置在配置文件中,以实现 SQL 的灵活配置。

MyBatis 并不完全是一种 ORM 框架,它的设计思想和 ORM 相似,只是它允许直接编写 SQL 语句,使得数据库访问更加灵活。因此,准确地说,MyBatis 提供了一种“半自动化”的 ORM 实现,是一种 “SQL Mapping” 框架。
下面展示一些 内联代码片

spring配置详解

别名
alias 设置别名 , 为bean设置别名 , 可以设置多个别名

<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="user" alias="user5"/>

Bean配置

<!--bean就是java对象,由Spring创建和管理-->
<!--
id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
如果配置id,又配置了name,那么name是别名
name可以设置多个别名,可以用逗号,分号,空格隔开
如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;
class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
<property name="name" value="Spring"/>
</bean>

import
团队的合作通过import来实现

<import resource="{path}/beans.xml"/>

IOC理论

先写一个UserDao接口

public interface UserDao {
void getUser();
}

写dao的实现类

public class UserDaoImpl implements UserDao {
public void getUser() {
System.out.println("获取用户信息");
}
}

写UserService的接口

public interface UserService {
void getUser();
}

写service实现类

public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
public void getUser() {
userDao.getUser();
}
}

测试

public class MyTest {
@Test
public void getUser() {
UserServiceImpl userService = new UserServiceImpl();
userService.getUser();
}
}

这是我原来的方式 , 开始大家也都是这么去写的对吧 . 那我现在修改一下

把Userdao的实现类增加一个

public class UserDaoMySqlImpl implements UserDao {
@Override
public void getUser() {
System.out.println("MySql获取用户数据");
}
}

紧接着我去使用mysql的话,就需要去service实现类里面修改对应的实现

public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoMySqlImpl();
@Override
public void getUser() {
userDao.getUser();
}
}

在假设, 我再增加一个Userdao的实现类

public class UserDaoOracleImpl implements UserDao {
@Override
public void getUser() {
System.out.println("Oracle获取用户数据");
}
}


那么我们要使用Oracle , 又需要去service实现类里面修改对应的实现 . 假设我们的这种需求非常大 , 这种方式就根本不适用了, 甚至反人类对吧 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性 太高了, 牵一发而动全身 .

那我们如何去解决呢 ?

我们可以在需要用到他的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下

public class UserServiceImpl implements UserService {
private UserDao userDao = new UserDaoImpl();
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}


现在去我们的测试类里 , 进行测试 ;

public class MyTest {
@Test
public void getUser() {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoMysqlImpl());
userService.getUser();
}
}

大家发现了区别没有 ? 可能很多人说没啥区别 . 但是同学们 , 他们已经发生了根本性的变化 , 很多地方都 不一样了 . 仔细去思考一下 , 以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对 象 , 把主动权交给了调用者 . 程序不用去管怎么创建,怎么实现了 . 它只负责提供一个接口 。

这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合 性大大降低 . 这也就是IOC的原型 !

2.2、IOC本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为 DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完 全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所 谓控制反转就是:获得依赖对象的方式反转了。
在这里插入图片描述
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解, 新版本的Spring也可以零配置实现IoC。 Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用 时再从Ioc容器中取出需要的对象。
在这里插入图片描述
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一 体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现 控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

第一个spring程序

搭建环境
导入Jar包

<!--spring核心支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>

编写代码
编写一个User实体类

@Data
public class User {
private String name;
}

编写spring配置文件

<?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">
<!-- bean就是Java对象,由spring创建和管理 -->
<bean id="user" class="com.caians.entity.User">
<property name="name" value="spring"/>
</bean>
</beans>

测试

@Test
public void test() {
//解析beans.xml文件,生成管理相应的bean对象
//获取spring的上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//getBean :参数即为spring配置文件中的bean的id
User user = (User) context.getBean("user");
System.out.println(user);
}

在这里插入图片描述

依赖注入DI

依赖注入(Dependency Injection,DI)。
依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 .
注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 .
1.构造器注入
之前的案例中已经详细使用了
2.set注入【重点】
要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is .
环境搭建:

@Data
public class Address {
private String address;
}
@Data
public class Student {
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String, String> card;
private Set<String> games;
private String wife;
private Properties info;
public void show() {
System.out.println("name=" + name
+ ",address=" + address.getAddress()
+ ",books="
);
for (String book : books) {
System.out.print("<<" + book + ">>\t");
}
System.out.println("\n爱好:" + hobbys);
System.out.println("card:" + card);
System.out.println("games:" + games);
System.out.println("wife:" + wife);
System.out.println("info:" + info);
}
}

1、常量注入

<!-- 常量注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
</bean>

测试:

@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student");
System.out.println(student);
}

2、Bean注入
注意点:这里的值是一个引用,ref

<!-- Bean注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
<property name="address" ref="address"/>
</bean>
<bean id="address" class="com.caians.entity.Address">
<property name="address" value="西安"/>
</bean>

3、数组注入

<!-- 数组注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
<property name="books">
<array>
<value>Java</value>
<value>Mysql</value>
<value>Spring</value>
</array>
</property>
</bean>

4、list注入

<!-- list注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
<property name="hobbys">
<list>
<value>演讲</value>
<value>上班</value>
<value>爬山</value>
</list>
</property>
</bean>

5、Map注入

<!-- Map注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
<property name="card">
<map>
<entry key="中国邮政" value="456456456465456"/>
<entry key="建设" value="1456682255511"/>
</map>
</property>
</bean>

6、set注入

<!-- Set注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
<property name="games">
<set>
<value>lol</value>
<value>王者</value>
<value>吃鸡</value>
</set>
</property>
</bean>

7、null注入

<!-- null注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
<property name="wife">
<null/>
</property>
</bean>

8、Properties注入

<!-- properties注入 -->
<bean id="student" class="com.caians.entity.Student">
<property name="name" value="Joson"/>
<property name="info">
<props>
<prop key="学号">10001</prop>
<prop key="性别"></prop>
<prop key="姓名">Joson</prop>
</props>
</property>
</bean>

测试结果:
在这里插入图片描述
拓展方式入职【了解】
测试环境

@Data
public class User {
private String name;
private int age;
}

1、P命名空间注入** : 需要在头文件中假如约束文件

导入约束 : xmlns:p="http://www.springframework.org/schema/p"
<!--1P命名空间注入** : 需要在头文件中假如约束文件-->
<bean id="user" class="com.caians.entity.User" p:name="Joson" p:age="18"/>

2、c 命名空间注入 : 需要在头文件中假如约束文件

导入约束 : xmlns:c="http://www.springframework.org/schema/c"
<!--2、c 命名空间注入 : 需要在头文件中假如约束文件-->
<bean id="user" class="com.caians.entity.User" c:name="Joson" c:age="18"/>

发现问题:爆红了,刚才我们没有写有参构造! 解决:把有参构造器加上,这里也能知道,c 就是所谓的构造器注入! 测试代码:

@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
System.out.println(user);
}

Bean的作用域
在Spring中,那些组成应用程序的主体及由Spring IoC容器所管理的对象,被称之为bean。简单地讲, bean就是由IoC容器初始化、装配及管理的对象 .

几种作用域中,request、session作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应 用框架),只能用在基于web的Spring ApplicationContext环境。

1、单例模式(spring默认机制)Singleton

当一个bean的作用域为Singleton,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对 bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在 创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都 是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。要在XML中将bean定义成singleton, 可以这样配置:

<bean id="user" class="com.caians.entity.User" scope="singleton">
<property name="name" value="Joson"/>
<property name="age" value="18"/>
</bean>

测试:

@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
User user1 = (User) context.getBean("user");
System.out.println(user==user1);
}

2、原型模式:每次从容器中get的时候,都会产生一个新对象 Prototype
当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导 致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都 会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们 获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有 状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。在XML中将bean 定义成prototype,可以这样配置:

<bean id="user" class="com.caians.entity.User" scope="prototype">
<property name="name" value="Joson"/>
<property name="age" value="18"/>
</bean>

AOP

11.1、什么是AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程 序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是spring框架中的一个 重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业 务逻辑各部分之间的耦合性降低,提高程序的可重用性。同时提高了开发效率。

11.2、AOP在spring中的作用
提供声明式事务;允许用户自定义切面

横切关注点:跨越应用程序多个模块的方法或功能。既是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点,如日志,安全,缓存,事务等单…
切面(ASPECT):横切关注点 被模块化 的特殊对象。即,它是一个类
通知(advice):切面必须要完成的工作。即,它是类中的一个方法
目标(target):被通知对象
代理(proxy):向目标对象应用通知之后创建的对象。
切入点(pointCut):切面 通知 执行的“地点”的定义
连接点(JointPoint):与切入点匹配的执行点

SpringAOP中,通过advice定义横切逻辑,spring中支持5中类型的advice:

通知类型 连接点 实现接口
前置通知 方法前 import org.springframework.aop.MethodBeforeAdvice
后置通知 方法后 import org.springframework.aop.AerReturningAdvice
环绕通知 方法前后 import org.aopalliance.intercept.MethodInterceptor
异常抛出通知 方法抛出异常 import org.springframework.aop.ThrowsAdvice
引介通知 类中增加新的方法属 性 import org.springframework.aop.IntroductionIntercepto
即AOP在不改变原有代码的情况下,去增加新的功能

11.3、使用spring实现AOP
【重点】使用AOP,必须导入一个依赖包

<!-- AOP依赖 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>

方式一:使用spring的API接口
创建一个UserService接口和UserServiceImpl

public interface UserService {
void add();
void delete();
void update();
void query();
}
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("增加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("修改了一个用户");
}
public void query() {
System.out.println("查询了一个用户");
}
}

编写通知类

//前置通知
public class BeforeLog implements MethodBeforeAdvice {
//method:需要执行的目标对象的方法
//objects:参数
//o:目标对象
public void before(Method method, Object[] objects, Object o) throws
Throwable {
System.out.println(o.getClass().getName() + "的" + method.getName()
+ "被执行了");
}
}
//后置通知
public class AfterLog implements AfterReturningAdvice {
//returnValue:返回值
public void afterReturning(Object returnValue, Method method, Object[]
args, Object target) throws Throwable {
System.out.println("执行力" + method.getName() + "返回结果为:" +
returnValue);
}
}


编写spring配置文件,注册Bean和配置aop

<!-- 注册bean -->
<bean id="userService" class="com.caians.service.UserServiceImpl"/>
<bean id="beforeLog" class="com.caians.log.BeforeLog"/>
<bean id="afterLog" class="com.caians.log.AfterLog"/>
<!--方式一: 使用原生的API接口 -->
<!-- 配置aop 需要导入aop的约束-->
<aop:config>
<!-- 切入点:pointcut 表达式:expression execution(要执行的位置) -->
<aop:pointcut id="pointcut" expression="execution(*
com.caians.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕-->
<aop:advisor advice-ref="beforeLog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
</aop:config>

测试

@Test
public void test() {
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add();
}

结果
在这里插入图片描述
方式二:自定义类实现AOP【主要是切面实现】
编写自定义切面类

//自定义切点类
public class DiyPointCut {
public void before() {
System.out.println("方法执行前");
}
public void after() {
System.out.println("方法执行后");
}
}

在spring配置文件里配置AOP

<!--方式二: 自定义类 -->
<bean id="diyPointCut" class="com.caians.diy.DiyPointCut"/>
<aop:config>
<!--自定义切面:ref:要引用的类-->
<aop:aspect ref="diyPointCut">
<aop:pointcut id="pointcut" expression="execution(*
com.caians.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>

测试

@Test
public void test() {
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) context.getBean("userService");
userService.add1();
}

结果
在这里插入图片描述
方式三:使用注解实现AOP
自定义切面类

@Aspect //标注这个类是一个切面
@Component
public class AnnotationPointCut {
@Pointcut("execution(* com.caians.service.UserServiceImpl.*(..))")
private void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("方法执行前");
}
@After("pointcut()")
public void after() {
System.out.println("方法执行后");
}
}

编写spring配置文件,开启注解扫描,开启AOP注解方式

<!-- 方式三 -->
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.caians.*"/>
<!-- 开启AOP注解方式 -->
<aop:aspectj-autoproxy/>

测试

public class MyTest {
@Test
public void test() {
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService)
context.getBean("userService");
userService.add();
}
}

结果

在这里插入图片描述
plicationContext context = new
ClassPathXmlApplicationContext(“applicationContext.xml”);
UserService userService = (UserService) context.getBean(“userService”);
userService.add1();
}


4. 结果

[外链图片转存中...(img-vTrYcgMm-1616230952977)]

> 方式三:使用注解实现AOP

1. 自定义切面类

```java
@Aspect //标注这个类是一个切面
@Component
public class AnnotationPointCut {
@Pointcut("execution(* com.caians.service.UserServiceImpl.*(..))")
private void pointcut() {
}
@Before("pointcut()")
public void before() {
System.out.println("方法执行前");
}
@After("pointcut()")
public void after() {
System.out.println("方法执行后");
}
}

编写spring配置文件,开启注解扫描,开启AOP注解方式

<!-- 方式三 -->
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.caians.*"/>
<!-- 开启AOP注解方式 -->
<aop:aspectj-autoproxy/>

测试

public class MyTest {
@Test
public void test() {
ClassPathXmlApplicationContext context = new
ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService)
context.getBean("userService");
userService.add();
}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值