ssm简单笔记

SSM

Javaweb的三大组件:Servlet,Filter,Listener;

复习JavaWeb

filter流程

image-20210806085748742

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对象收到这个数据)

image-20210806185956945

将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请求封装的数据

image-20210807101446208

get请求封装数据

image-20210807101855937

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都要自动生成

泛型依赖注入的原理

image-20210810195813570

将数组转换成集合

Arrays.asList(数组名)

AOP

image-20210812165605661

如何将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的执行顺序

环绕前置–>普通方法前置–>目标方法执行–>普通正常返回/出现异常–>普通后置–>环绕正常返回/出现异常–>环绕后置

image-20210816101059968

多切面执行顺序

image-20210816101158530

image-20210816101224967

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

image-20210818103218030

解决办法,在jsp页面上加上

<%@ page contentType="text/html;charset=UTF-8" language="java"
isErrorPage="true" 
%> 其实主要是加上isErrorPage="true" ,告诉tomcat可能会报错

ModelAttribute原理

image-20210819225004017

SpringMVC的运行流程

image-20210828203135169

SpringMVC和Spring进行整合时,Spring的Service不能自动装配SpringMVC的Controller是因为在Spring中默认讲Spring作为父容器,SpringMVC作为子容器。子容器可以拿父容器的东西,父容器不能拿子容器

image-20210829100815284

mybatis中的知识点的简单记录

https://199604.com/709

mybatis中一级缓存和二级缓存的示意图

image-20210906104506413

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值