SSM
Javaweb的三大组件:Servlet,Filter,Listener;
复习JavaWeb
filter流程
Listener
八个:ServletRequest(2)、HttpSession(2)、ServletContext(2)
2:生命周期监听器,属性变化监听器
4(HttpSession):除了上面那两个外,还有额外的两个(活化钝化监听器、绑定解绑监听器)
掌握的监听器:
ServlertContextListener(生命周期):监听ServletContext的创建和销毁(监听服务器的启动和停止);服务器启动创建一个ServletContext对象,服务器停止,销毁创建的ServletContext对象;
ServletContext:
1、一个web项目对应一个ServletContext,它代表web项目的信息
2、还可以作为最大的域对象在整个项目的运行期间共享数据
监听器的使用方法:
1.先实现对应的监听器接口
2.去web.xml进行配置;注意:有两个Listener是JavaBean需要实现的接口,(HttpSessionActivitionListener,HttpSessionBindingListener)
AJAX和JSON
JSON:(js对象表法)是一种轻量级的数据交换格式(与xml相比较)
一个复杂的js对象
var student = {
lastName: "张山",
age: 18,
car: {pp: "baoma", price: "15555555555"},
infos: [{bookName: "西游记", price: 19}, 18, true]
};
如果服务器返回给浏览器的样子是js对象这个样子的,浏览器使用js解析就很方便;
JSON
//json要求和js对象是一样的,只不过key必须是字符串
//js对象在声明的时候是否加双引号是可以选择的
var student2 = {
"lastName": "张山",
"age": 18
};
//JSON(js的内置对象)这个是js提供的将js对象转换成json(应该是js对象的字符串表示法)字符串
var strjson= JSON.stringify(student2);
alert(typeof strjson);
alert(strjson);
两个重要的API:
1、将js对象转换为JSON
JSON.stringify(js对象)
2、将JSON对象转换成js’对象
JSON.parse(JSON对象);
AJAX
AJAX:synchronous Javascript And XML(异步JavaScript和XML)
AJAX:是一种无刷新页面与服务器的交互技术。(保持页面不刷新就能得到服务器的数据)
原来的交互:
1、发送请求
2、服务器收到请求,调用队对应的servlet进行处理;servlet处理完成之后会有响应信息生成;
3、浏览器收到了服务器响应的数据,把之前的页面清空,展示新的数据;(效果就是页面刷新)
现在的交互:(XmlHttpRequest对象)
1、XmlHttpRequest对象帮我们发送请求
2、服务器收到请求后,调用对应的servlet进行处理;servlet处理完成会有响应信息生成;
3、XmlHttpRequest对象收数据(浏览器就感受不到这个数据了;xml对象收到这个数据)
将fJava中的Object对象转换成Json对象的包
代码演示:
Map<String, Object> map = new HashMap<>();
map.put("lastName","zs");
map.put("age",18);
//1、转成json
Gson gson = new Gson();
String str = gson.toJson(map);
response.getWriter().write(str);
引入的依赖:(去maven仓库下载就可以了)
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
改变了我们传统的交互反射光hi就
1、发请求;
2、服务器收到请求,处理请求经常要给页面携带数据。request.setAtteribute(“map”,map);转发到页面
3、浏览器收到页面数据,在页面中使用el表达式获取数据;
导致页面整个刷新,造成了很大的服务器负担;
只让服务器返回我们需要的部分数据即可;不用返回整个页面;xhr代替浏览器来接收响应,发送请求;利用dom增删给的方式改变页面的效果;
异步无刷新页面技术
异步:不会阻塞浏览器
同步:会阻塞浏览器;因为需要等到服务器处理完整个请求,完成响应后才能做其他事情
什么是ajax:
ajax就是xhr对象向服务器发送请求,并受到响应数据,利用dom增删改的方式改变页面效果
Ajax中get请求和post请求的用法是一样的,只是一个发送的是get请求一个发送的是post请求,区别是get请求时将数据封装在请求的?后面,而post请求是将数据封装在了请求体中
post请求封装的数据
get请求封装数据
IOC和DI
IOC:(Inversion(反转) Of Control)控制反转;
控制:资源获取的方式;
主动式:(要什么资源都自己创建即可)
BookServlet{
BookService bs= new BookService();
AirPlane ap=new AirPlane();
}
被动式:资源的获取不是我们自己创建,而是交给一个容器来创建和设置;
BookService{
BookService bs;
public void test01(){
bs.checkout();
}
}
容器:管理所有的组件(有功能的类)
假设,BookServlet受容器管理,BookService也受容器管理;容器可以自动的探查出那些组件(类)需要用到另一写组件(类)﹔容器帮我们创建BookService对象,并把BookService对象赋值过去;
容器:主动的new资源变为被动的接收咨源·
(容器)婚介所:主动获取变为被动接收;
DI(Dependency Injection)依赖注入;
容器能知道哪个组件(类)运行的时候,需要另一个类(组件);容器通过反射的形式,将容器中准备好BookService对象注入(利用反射给属性赋值)到BookServce中
HelloWorld;(通过各种方式给容器中注册对象(类似于婚庆所的注册会员)),以前是自己new对象现在所有的对象都交给容器创建;给容器中注册组件
以后编写的流程;
HelloWorld
1、导包(4个jar包:spring-context、spring-core、spring-beans、spring-expression)
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.3.9</version>
</dependency>
2、写配置(ioc.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">
<!-- 注册一个person对象,Spring会自动创建一个Person对象-->
<!--
一个bean标签可以注册一个组件(对象、类)
id:这个对象的唯一标识
class:要写的注册的组件的全类名
-->
<bean id="person" class="com.pzx.spring.bean.Person">
<!-- property 标签为对象的属性赋值
name是用来指定属性名称,
value是用来指定属性值
-->
<property name="lastName" value="张三"></property>
<property name="age" value="18"></property>
<property name="email" value="zs@guigu.com"></property>
<property name="gender" value="男"></property>
</bean>
</beans>
3、测试 (ClassPathXmlApplicationContext当前配置文件在ClassPath下)
@Test
public void test(){
//ApplicationContext:表示ioc容器
//当前应用的xml配置文件在内路径下
//ClassPathXmlApplicationContext当前配置文件在ClassPath下
//根据Spring的配置文件得到ioc容器对象
ApplicationContext ioc = new ClassPathXmlApplicationContext("ioc.xml");
Person person = ioc.getBean("person", Person.class);
System.out.println(person);
}
//结果 Person{lastName='张三', age=18, gender='男', email='zs@guigu.com'}
HelloWorld的小总结
有几个小细节:(对象的创建都是通过反射来实现的)
1、ApplicationContext(IOC容器的接口)
2、给容器注册了一个组件;我们也从容器中按照id拿到了这个组件的对象?
- 组件的创建工作是容器来替我们完成的
* Person对象是什么时候创建好的呢?
* 容器中对象的创建是在容器创建完成之后就已经创建好了;
3、同一个组件在ioc容器中是单实例的,容器启动完成就已经创建好了
4、容器中如果没有这个组件,获取组件会报异常
* org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'person3' available
5、ioc容器在创建这个组件对象时,(property)会利用setter方法为JavaBean的属性赋值
6、JavaBean的属性名使用什么决定的?getter/setter方法,属性名是去掉set,后面那串字母首字母小写
* 注意不要随便该getter/setter,所有的getter/setter都要自动生成
泛型依赖注入的原理
将数组转换成集合
Arrays.asList(数组名)
AOP
如何将Spring中的一个类定义为一个切面类
将Spring中的一个类定义为切面类
在类上加上@Aspect 和 @Component这两个注解
其中@Aspect的作用是将这个类声明为一个切面类
@Component这个注解的作用是表示将这个类注入到IOC容器中
SpringAOP五大通知注解
在以下方法上面加上这些注解之后,还得在注解里面加上execution()
-
@Before:在目标方法执行之前运行 前置通知
-
@After:在目标方法执行完成之后运行 后置通知
-
@AfterReturning:在目标方法正常返回后 返回通知 这个注解里面可能还要加上
@AfterReturning(value = "hahaMyPoint()" ,returning="result") @AfterReturning 这个注解里面可能还要加上returning的值用来表明返回的执行结果
-
@AfterThrowing:在目标方法抛出异常后执行 异常通知
@AfterThrowing(value = "hahaMyPoint()",throwing="exception") 这个注解也有可能要加上throwing,用来表示返回的异常信息
代码演示
/**
* 细节四:我们可以在通知方法运行的时候,拿到目标方法的详细信息学;
* 1)只需要为通知方法的参数列表上写一个参数:
* JoinPoint joinPoint:封装了目标方法的详细信息
*
* 2)、告诉Spring哪个参数是用来接收异常的
*
*
* 3)、Exception exception:指定通知方法可以接收哪些异常(一般都是往大的方面写)
*
* 有点像ajax请求
* ajax.post(url,function(abc){
* alert(abc);
* })
*
*/
//想在目标方法出现异常后执行
// @AfterThrowing(value = "execution(public int com.pzx2.impl.MyMathCalculator.*(int ,int ))",throwing="exception")
@AfterThrowing(value = "hahaMyPoint()",throwing="exception")
public static void logException(JoinPoint joinPoint , Exception exception) {
Signature signature = joinPoint.getSignature();
String name = signature.getName();
System.out.println("[LogUtils-异常]【"+name+"】方法出现异常了,异常信息是"+exception+ ":已经通知测试小组进行排查");
}
- @Around:环绕 (这个功能最强大) 环绕通知
四个通知方法的执行顺序
try {
@Before
method.invoke(obj,args);
@AfterReturning
} catch (Exception e) {
@AfterThrowing
} finally {
@After
}
切入点表达式的几种常见的写法
切入点表达式的固定写法
固定格式:execution(访问权限符 返回值类型 方法的全签名(参数类型))
/**
* 切入点表达式的写法;
* 固定格式:execution(访问权限符 返回值类型 方法的全签名(参数类型))
* 通配符:
* * :1)、匹配一个或者多个字符:execution(public int com.pzx2.impl.MyMath*.*(int ,int ))
* 2)、匹配任意一个参数:第一个是int类型,第二个参数是任意类型;(一共匹配两个类型)
* execution(public int com.pzx2.impl.MyMathCalculator.*(int ,* ))
* 3)、只能匹配一层路径
* 4)、权限位置的*不能表示任意的权限值,权限位置不写,就带表任意的访问修饰符(public【是可选项的】)
*
*
* .. : 1)、匹配任意多个参数
* execution(public int com.pzx2.impl.MyMathCalculator.*(..))
* 2)匹配任意多层路径
* execution(public int com.pzx2.impl..MyMathCalculator.*(..))
*
* 记住两种:
* 最精确的写法:execution(public int com.pzx2.impl.MyMathCalculator.add(int,int))
* 最模糊的:execution(* *.*(..)):千万别写
*
* 还可以使用下面的表达式
* "&&"、"||"、"!"
* MyMathCalculator.add(int , double)
* 切入点表达式要满足下面两个表达式才行
* execution(public int com.pzx..MyMath*.*(..)) && execution(* *.*(int,int))
*||:满足一个表达式即可
*
*
*/
将切入点表达式抽取出来可重复使用(同一个类里面的引用直接用方法名加上参数列表即可,而不是同一个类之间的引用的话要用全类名)
/** 抽取可重用的切入点表达式;
* 1、随便声明一个没有实现的返回void的空方法
* 2、给方法上标注@Pointcut
*/
@Pointcut("execution(* com.pzx2.impl..MyMathCalculator.*(..))")
public void hahaMyPoint(){
}
环绕通知代码演示
/**
* @Around :环绕通知是Spring中最强大的通知方法
* @Around:环绕动态代理;
*
* try{
* //前置通知
* method.invoke(obj,args);
* //返回通知
* }catch(Exception e){
* //异常通知
* }finally{
* //后置通知
* }
*
* 四合一就是环绕通知
* 环绕通知中有一个参数 : ProceedingJoinPoint pjp
*
* 环绕通知:是优先于普通通知执行,执行顺序;
* [普通方法执行]
* {
* try{
* 环绕前置
* 环绕执行:目标方法执行
* 环绕返回
* }catch(){
* 环绕出现异常
* }finally{
* 环绕后置
* }
*
*
*
*
* }
* [普通后置]
* [普通方法返回 / 方法异常]
*
*
* 新的顺序;
* 注意:这个是Spring4的运行顺序 环绕前置-->普通方法前置-->目标方法执行-->环绕正常返回/出现异常-->环绕后置-->普通后置-->普通返回或者异常
* Spring5的顺序不同
*
*
*
*/
@Around("hahaMyPoint()")
public Object myAround(ProceedingJoinPoint pjp) {
Object proceed=null;
Signature signature = pjp.getSignature();
String name = signature.getName();
try {
Object[] args = pjp.getArgs();
//利用反射推进目标方法即可,就是method.invoke(obj,args);
//Before
System.out.println("【环绕前置】【" + name + "方法开始】");
proceed = pjp.proceed(args);
//@AfterReturning
System.out.println("【环绕返回通知】【"+name+"方法返回,返回值"+proceed+"】");
} catch (Throwable throwable) {
//@AfterThrowing
System.out.println("【环绕方法出现异常】【" + name + "】方法出现异常,异常原因:" + throwable);
//为了让外界知道这个原因,这个异常一定要抛出去
throw new RuntimeException(throwable);
} finally {
// @After()
System.out.println("【环绕后置通知】 【" + name + "】方法结束");
}
//反射调用后,返回值一定也返回出去
return proceed;
}
当普通方法与环绕方法一起执行的时候的方法执行顺序
Spring5的执行顺序
环绕前置–>普通方法前置–>目标方法执行–>普通正常返回/出现异常–>普通后置–>环绕正常返回/出现异常–>环绕后置
多切面执行顺序
xml格式配置通知方法
<!-- 需要AOP名称空间 -->
<aop:config>
<!-- 声明一个全局的切入点表达式 -->
<aop:pointcut id="globalPoint" expression="execution(* com.xml.impl.*.*(..))"/>
<!-- 指定切面 @Aspect -->
<aop:aspect ref="logUtils">
<!-- 配置哪个方法是前置通知;method指定方法名
logStart@Before("切入点表达式")
-->
<!-- 这个表达式只能当前切面能用 -->
<aop:pointcut id="mypoint" expression="execution(* com.xml.impl.*.*(..))"/>
<aop:before method="logStart" pointcut-ref="mypoint"/>
<aop:after-returning method="logReturn" returning="result" pointcut-ref="mypoint"/>
<aop:after-throwing method="logException" throwing="exception" pointcut-ref="mypoint"></aop:after-throwing>
<aop:after method="logEnd" pointcut-ref="mypoint"></aop:after>
<aop:around method="myAround" pointcut-ref="mypoint"></aop:around>
</aop:aspect>
<aop:aspect ref="validateApsect">
<aop:before method="logStart" pointcut-ref="globalPoint"></aop:before>
<aop:after-returning method="logReturn" returning="result" pointcut-ref="globalPoint"></aop:after-returning>
<aop:after-throwing method="logException" throwing="exception"
pointcut-ref="globalPoint"></aop:after-throwing>
<aop:after method="logEnd" pointcut-ref="globalPoint"></aop:after>
</aop:aspect>
</aop:config>
高版本的tomcat,在SpringMVC使用DELETE、PUT请求时爆错405
解决办法,在jsp页面上加上
<%@ page contentType="text/html;charset=UTF-8" language="java"
isErrorPage="true"
%> 其实主要是加上isErrorPage="true" ,告诉tomcat可能会报错
ModelAttribute原理
SpringMVC的运行流程
SpringMVC和Spring进行整合时,Spring的Service不能自动装配SpringMVC的Controller是因为在Spring中默认讲Spring作为父容器,SpringMVC作为子容器。子容器可以拿父容器的东西,父容器不能拿子容器
mybatis中的知识点的简单记录
https://199604.com/709