狂肝最强javaEE框架高强度学习

SpringBean容器:
bean就是java对象,容器负责java对象整个生命周期的管理,包括创建修改销毁等

IOC控制反转
IOC:是一种思想
IOC容器:IOC思想的实现容器

DI
实现IOc的方法之一,依赖注入,就是再IOC运行期间,动态的将依赖关系注入到对象之中

通过Ioc思想,引入Ioc容器,利用依赖关系注入实现对象之间的解耦.
设计上说明ioc,作用,用来降低代码之间的耦合性,实现方式:DI,DI有两种方式实现

注册Bean,在类上使用,一旦被类扫描到,就生成Bean对象注册到容器中,注解方式
Controller:web请求响应处理,控制器层 完成请求数据校验等操作
Service:业务逻辑的服务层 根据方法参数完成业务逻辑
Repository:数据访问层 关系型数据库的访问操作
Component:一般的组件
方式二
@Bean注释在方法上
更加灵活可以修改属性

方式三
@configuration
用来自定义配置某些资源

方式四:factorybean
工厂的bean对象,
工厂模式生产制定的对象

传统三层架构设计:Controller,Service.DAO

装配bean
@Autowired 自动装配
@Qualifier (“名字”)
@Resourse jdk spring也做了实现spring也做了实现

@Scope(prototype)的作用
Bean对象获取时,都会new一个新对象,singleTon,同一个对象
T通常使用在有状态Bean

Bean的生命周期
1.实例化Bean
2,依赖注入
3.注入 Aware 接口的方法参数对象,如顺序执行BeanNameAwar等e
4.Bean初始化之前,执行beanPostProcessor的before方法
5.Bean对象初始化:执行一些注解和接口方法
6.执行beanPostProcessor的after方法
7.容器关闭时,执行Bean对象的销毁方法

springboot项目准备
1.创建普通的maven项目
2.调整pom.xml文件:引入springBoot的相关依赖
3.src/main/resources
创建public static 存放web静态资源文件
创建application.properties,springboot默认的配置文件
4.随便创建启动类:必须写在某个包下,启动时自动扫描自动类所在包
5.修改debug日志:application.property文件里Debug
6.调整启动不报错
7.直接运行启动类

前段相对路径小坑儿

js是以在的html路径作为相对路径的起点

css是以文件自身的请求路径作为请求的起点

前端代码:Ajax详情解析:
异步请求,不会跳转页面,不会阻塞后续的代码,接收到响应数据执行回调方法:
(1)响应码200,执行success回调函数
(2)4XX,5xx执行失败的回调函数

浏览器提供了原生ajax技术实现
目前都使用jQuery框架,万变不离其宗

$(function(){ //html页面加载执行完毕后执行的方法
    $("#login_form").submit(function(){//绑定表单的提交事件,提交后执行后边的方法
        //执行ajax提交
        $.ajax({
            //从这里获得resp
            //url:"../data/login.json",
            url:"../data/login2.json",
            type:"get",//请求方法 
            //dataType:"",//请求数据类型Content-type
            data:$("#login_form").serialize(),//请求数据:使用表单的数据,键等于值
            contentType:"json",//响应数据类型:Content-Type
            //返回一个json的数据
            success:function (resp) {//响应状态为2开头进入success
                //返回数据success == true 跳转到maven页面
                if (resp.success == true){
                    //把地址栏url该会指定的值
                    window.location.href = "main.html";
                }else{
                    alert("错误码: " + resp.code+"\n错误信息: "+resp.message)
                    //alert(JSON.stringify(resp))//提示框:json对象转为字符串
                }
            },
            error:function (req,textStatus,err) {//4大头响应状态码
                alert(req.status)
            }
        })

        //验证alert("submit")
        return false;//返回值决定是否是使用表单默认提交
    })
})

springMVC
Tomcat和servlet执行流程
资源:
(1)如果是静态资源,tomcat直接返回
(2)如果是servlet
----调用service()
----request:解析http协议的请求数据,封装为request
----response:调用service()还没有反会响应,但已经创建了响应对象
----tomcat根据response对象构造http协议的相应数据

mvc模型’’在这里插入图片描述
RequestMapping在这里插入图片描述

@Controller
public class Test2Controller {
    @RequestMapping("/test2")
    public String test(){
        return "forward:/home.html";
    }
}

String返回类型的作用
在这里插入图片描述
@controller:web前端控制器
@RequestMapping:类和方法上,value路径,method指定服务的方法,method没有,默认支持所有方法
@ResponseBody:返回值作为相应体
返回类型为String,字符串作为响应体的内容
返回类型为自定义的java类型,Object,序列化为JSON字符串
组合注释
1.RestController:controller + ResponseBody的注解
2.GetMapping:方法上使用了requestmapping+get
3.PostMapping:
Controller中请求映射方法中的参数
(1)@RequestParam:除了application/json,其他的都可以通过key获取value,默认是必填的,非必填指定

required=false
可以接受form-data,包括文件 
 @RequestMapping("login")
    public Object login(@RequestParam String username,@RequestParam String password){
         log.debug("获取到路径请求参数 username "+ username + "password" + password);
         Map<String,Object> map = new HashMap<>();
         map.put("ok",true);
         return map;
     }
     @RequestMapping("/register")
    public Object register(@RequestParam String username, @RequestParam String password, @RequestParam MultipartFile file) throws IOException {
        log.debug("获取请求路径参数 : username={},  password={}",username,password);
        log.debug("头像信息,名称={},内容={}",file.getOriginalFilename(),new String(file.getBytes()));
         Map<String,Object> map = new HashMap<>();
         map.put("ok",true);
         return map;
     }
     public Object holiday(@PathVariable String day){
        log.debug("获取到路径请求参数" + day);
        Map<String,Object> map = new HashMap<>();
        map.put("ok",true);
        return map;
     }

(2)POJO对象,和使用@RequestParam作用一样.

使用哪种方式获取请求数据:
(1)相对来说,pojo比@RequestParam更方便书写
(2)请求数据比较少,一般是不使用json,如果没有自定义类型对应,可以直接使用包装类型

(3)请求数据比较多,可能设计为请求数据类型可能设计为json,表单默认格式,formdata(pojo)
@RequestBody用json

RequstPart
二进制文件,默认required=true

@PostMapping("/file")
    public Object file(@RequestPart MultipartFile file) throws IOException {
        log.debug("头像信息,名称={},内容={}",file.getOriginalFilename(),new String(file.getBytes()));
        Map<String,Object> map = new HashMap<>();
        map.put("ok",true);
        return  map;
    }

SevletApi
和原生servlet差不多,直接作为方法参数,springmvc会传入Servlet对象
一般是:reponse返回二进制,自定义输出,如二进制文件,session的处理

Springmvc请求和响应,后端使用
(1)返回试图,不带responsebody注解,返回类型为String

(2)返回json数据:方法上带Responsebody注解(类上也是作用在方法上,返回类型为Object)

(3)请求数据类型为json@RequestBody,如果报错,请求数据有某个key,检查访问数据格式,反序列化的java对象中没有该属性,报错反序列化的java对象中有某个属性,请求json数据没有该key,不会报错,java中的属性就是默认值;不建议使用基本数据类型

(4)请求数据类型不是json,或是get请求:
使用pojo,其他的能看懂
注意事项:如果发现pojo对象的属性为null,一定是请求没有这个key

(5)Servlet相关Api:session相关

Url变量绑定:
@pathVariable
HandlerInterceptor拦截器:作用和filter类似,由mvc提供
在这里插入图片描述
前后端交互注意事项
在这里插入图片描述
前段的调试手段:开发者工具
后端Debug
出现什么问题找前一个流程的逻辑

用户统一的会话管理实现:HandlerIntertceptor
服务端中要考虑的统一管理服务资源
开放的权限 登录后访问的权限(登录前不允许访问)
文章列表,新增修改html加入黑名单,禁止访问
(1)前端资源

(2)后端资源 用户登录注册(/user/**)

黑白名单:List<白名单>,List<黑名单>做一个业务,白名单允许操作,黑名单不允许操作
在这里插入图片描述
添加拦截器使用黑白名单的思想,白名单设置要拦截资源的路径,黑名单要排除要拦截的资源路径

实际配置资源路径,会考虑:配置最小集 + 灵活扩展(可维护性)
SpringMVC
在这里插入图片描述
HandlerInterceptor,Filter
(1)可以同时匹配多个
(2)方法返回boolean类型,表示是否调用链是否往下执行
(3)如果需要往下执行,return true
(4)如果不能继续访问,return false;if(条件)返回响应给客户端 return false;

ControllerAdvice
在这里插入图片描述
1.当前类为一个Controler的统一切面类
2.可以定义统一处理的方法
@controllerAdvice
public class XXX{
@ExceptionHandler(异常.class)
public 返回类型 方法名(传入参数)
}
在这里插入图片描述

 @ExceptionHandler(AppException.class)
    public Object handle1(AppException e){
        JSONResponse json  = new JSONResponse();
        //自定义异常,保存我们的错误码和错误消息
        json.setCode(e.getCode());
        json.setMessage(e.getMessage());
        log.debug(transfer(e));
        //非自定义异常(英文的错误消息,堆栈信息,不能给用户看):
        // 指定一个错误码,错误消息(未知错误,请联系管理员)
        return json;
    }
    @ExceptionHandler(Exception.class)
    public Object handle2(Exception e){
        JSONResponse json  = new JSONResponse();
        //自定义异常,保存我们的错误码和错误消息
        json.setCode("ERR000");
        json.setMessage("未知错误,请联系管理员");
        log.debug(transfer(e));
        //非自定义异常(英文的错误消息,堆栈信息,不能给用户看):
        // 指定一个错误码,错误消息(未知错误,请联系管理员)
        return json;
    }

异常需要掌握的
(1)出现异常时,代码执行的顺序(se)
(2)如何抛异常?手动抛异常(自定义异常),代码出bug抛异常
(3)如何处理异常?框架封装了我们的trycatch,需要使用统一异常处理的方案
(4)如何根据异常找到出现异常的代码行,调试代码
根据堆栈信息,查找哪个类,哪个方法抛出的,分析try catch,分析我们的代码行,具体是哪一行代码
(3)ControllerAdvice
类实现ResponseBodyAdvice接口,根据条件重写响应体内容
重写support: 返回boolean,表示执行Controller请求映射方法后,是否重写beforeBodyWrite:怎么样重写,使用response对象来重写

AOP
概念:面向切面编程,属于一种编程思想
在这里插入图片描述
在这里插入图片描述
(1)继承方式
静态代理设计模式:
继承原始类/被代理类,子类就是代理类
重写父类方法,方法中调用父类方法前后加入增强业务

(2)接口的方式
原始类.被代理类,代理类实现同一个接口
使用被代理对象来创建创建代理类-------public 代理类(被代理类){}
代理类接口方法重写,是调用被代理类对象的方法前后加入增强业务

静态织入技术

在这里插入图片描述

织入时机:编译期,类加载期
代表技术ASpectJ

动态代理
AOP
(1)静态代理设计模式
(2)静态织入
(3)动态代理
java说AOp,基本指SpringAop,基本上指动态代理

运行期间动态的织入

动态代理的实现方式:
Jdk实现:
要求被代理实现接口
通过JDK的InvocationHandler,Proxy.newP roxyInstance,来生成代理类
在这里插入图片描述

Spring提供aspectJ的注解语法支持,本质上还是给予jdk和CGLIB来实现-----方法增强

@Aspect//进行切面编程
@Component
//连接点
public class TestAOP {
    //切面地点
    //包下任意类.任意方法,任意参数
    @Pointcut("execution(* com.example.mvclearn.controller.*.*(..))")
    public void loginPointcut(){

    }
}

AOP术语

@Aspect//进行切面编程,定义切面
@Component
//连接点
public class TestAOP {
    //切面地点,定义切点
    //包下任意类.任意方法,任意参数
    @Pointcut("execution(* com.example.mvclearn.controller.*.*(..))")
    public void loginPointcut(){

    }
    //通知,前置通知,传入切点方法名()
    @Before("loginPointcut()")
    public void beforeRequest(){
        System.out.println("前置通知");
    }
    @After("loginPointcut()")
    public void afterRequest(){
        System.out.println("请求映射方法执行完毕");
    }
    @AfterReturning
    public void afterRequestReturn(){
        System.out.println("请求映射方法返回");
    }
    @AfterThrowing("loginPointcut()")
    public void afterRequestThrow(){
        System.out.println("请求映射方法抛出异常");
    }
    //环绕通知

}

在这里插入图片描述
对AOP的理解
在这里插入图片描述
(3)Spring动态代理
织入时机:运行期(启动就生成)
实现方式:
1.JDK:基于接口实现(被代理类实现接口,接口方法需要增强)
API:InvocationHandler,Proxy
原理:运行时,动态生成字节码代理类,进行类加载,容器中都是代理类对象
2.CGLIB:基于继承实现(被代理类可以不实现接口)
原理:cglib框架生成代理类,cglib又基于asm字节码来生成增强代码

Mybatis
建议xml配置方法
jdbc操作回顾
在这里插入图片描述
ORM框架:
Mybatis
在这里插入图片描述
实体类

配置mapper接口

Mybatis执行流程
在这里插入图片描述
Dao层单元测试方法
在这里插入图片描述
为什么可以使用UserMapper接口呢
@mapper注解

Mybatis框架基于扫描容器中mapper注解的接口,使用Aop动态的生成代理类
调用Mapper实现类的方法

练习略…

Mybatis关系映射
一对一映射

在这里插入图片描述
property 属性:指定 Article 中对应的属性,即用户。
resultMap 属性:指定关联的结果集映射,将基于该映射配置来组织用户数据。
columnPrefix 属性:绑定一对一对象时,是通过 columnPrefix+association.resultMap.column
来映射结果集字段。association.resultMap.column是指 标签中 resultMap属性,
对应的结果集映射中,column字段。

多对多映射


```xml
<resultMap>结果集映射中,一对多关系需要使用<collection>标签,使用方法和<association>类似。
以下为 UserMapper.xml 的结果集映射配置:
以下是单元测试代码:
<select id="selectAll" resultMap="BaseResultMap">
   select
   a.id a_id,
   a.title a_title,
   a.content a_content,
   a.view_count a_view_count,
   a.user_id a_user_id,
   a.create_time a_create_time,
   u.id,
   u.username,
   u.password,
   u.nickname,
   u.sex,
   u.birthday,
   u.head,
   u.create_time
   from article a
   join user u
   on u.id=a.user_id
</select>
<!-- 定义结果集映射关系:绑定结果集字段和转换的java对象之间的关系 -->
<resultMap id="BaseResultMap" type="org.example.model.User">
    <!-- 结果集字段和java对象属性的映射 -->
    <id column="id" property="id" />
    <result column="username" property="username" />
    <result column="password" property="password" />
    <result column="nickname" property="nickname" />
    <result column="sex" property="sex" />
    <result column="birthday" property="birthday" />
    <result column="head" property="head" />
    <result column="create_time" property="createTime" />
    <collection property="articles"
                columnPrefix="a_"
                resultMap="org.example.mapper.ArticleMapper.BaseResultMap" />
</resultMap>

```java
package org.example.mapper;
import org.example.model.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
//指定为Spring环境中的单元测试
@RunWith(SpringRunner.class)
//指定为SpringBoot环境的单元测试,Application为启动类
@SpringBootTest(classes = Application.class)
//使用事务,在SpringBoot的单元测试中会自动回滚
@Transactional
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;
    @Test
    public void selectAll(){
        List<User> users = userMapper.selectAll();
        users.stream()
               .forEach(System.out::println);
   }
}

动态sql语句
标签

<insert id="insert" parameterType="org.example.model.User"
useGeneratedKeys="true" keyProperty="id">
 insert into user(
         username,
         password,
         nickname,
          <if test="sex != null">
           sex,
          </if>
         birthday,
         head
     ) values (
         #{username},
         #{password},
         #{nickname},
          <if test="sex != null">
           #{sex},
          </if>
         #{birthday},
         #{head}

注意 test 中的 sex,是传入对象中的属性,不是数据库字段。

标签
之前的插入用户功能,只是有一个 sex 字段可能是选填项,如果有多个字段,一般考虑使用标签
结合标签,对多个字段都采取动态生成的方式。
标签中有如下属性:
prefix:表示整个语句块,以prefix的值作为前缀
suffix:表示整个语句块,以suffix的值作为后缀
prefixOverrides:表示整个语句块要去除掉的前缀
suffixOverrides:表示整个语句块要去除掉的后缀

<insert id="insert" parameterType="org.example.model.User"
useGeneratedKeys="true" keyProperty="id">
 insert into user
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username != null">
         username,
        </if>
        <if test="password != null">
         password,
        </if>
        <if test="nickname != null">
         nickname,
        </if>
        <if test="sex != null">
         sex,
        </if>
        <if test="birthday != null">
               birthday,
        </if>
        <if test="head != null">
         head,
        </if>
        <if test="createTime != null">
         create_time,
        </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
        <if test="username != null">
         #{username},
        </if>
        <if test="password != null">
         #{password},
        </if>
        <if test="nickname != null">
         #{nickname},
        </if>
        <if test="sex != null">
         #{sex},
        </if>
        <if test="birthday != null">
         #{birthday},
        </if>
        <if test="head != null">
         #{head},
        </if>
        <if test="createTime != null">
         #{createTime},
        </if>
    </trim>
</insert>

在以上 sql 动态解析时,会将第一个 部分做如下处理:
基于 prefix 配置,开始部分加上 (
基于 suffix 配置,结束部分加上 )
多个 组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于
suffixOverrides 配置去掉最后一个 ,
注意 <if test=“createTime != null”> 中的 createTime 是传入对象的属性

以上标签也可以使用 替换。
单元测试代码如下:
根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容。
UserMapper 接口中修改用户方法:根据传入的用户 id 属性,修改其他不为 null 的属性:
UserMapper.xml 中添加更新用户 sql:

<select id="selectByCondition" parameterType="org.example.model.User"
resultMap="BaseResultMap">
   select id, username, password, nickname, sex, birthday, head, create_time
       from user
    <where>
        <if test="username != null">
           and username=#{username}
        </if>
        <if test="password != null">
           and password=#{password}
        </if>
        <if test="nickname != null">
           and nickname=#{nickname}
        </if>
        <if test="sex != null">
           and sex=#{sex}
        </if>
        <if test="birthday != null">
           and birthday=#{birthday}
        </if>
        <if test="head != null">
           and head=#{head}
        </if>
        <if test="createTime != null">
           and create_time=#{createTime}
        </if>
    </where>
</select>
@Test
public void selectByCondition(){
    User user = new User();
    user.setUsername("e");
    user.setPassword("5");
    List<User> users = userMapper.selectByCondition(user);
    System.out.println(users);
}
@Test
public void selectByCondition2(){
    User user = new User();
    user.setSex(false);
    List<User> users = userMapper.selectByCondition(user);
    System.out.println(users);
}

标签
根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容。
UserMapper 接口中修改用户方法:根据传入的用户 id 属性,修改其他不为 null 的属性:
UserMapper.xml 中添加更新用户 sql:

<update id="updateById" parameterType="org.example.model.User">
   update user
        <set>
            <if test="username != null">
               username=#{username},
            </if>
            <if test="password != null">
               password=#{password},
            </if>
            <if test="nickname != null">
               nickname=#{nickname},
            </if>
            <if test="sex != null">
               sex=#{sex},
            </if>
            <if test="birthday != null"> 
               birthday=#{birthday},
            </if>
            <if test="head != null">
               head=#{head},
            </if>
            <if test="createTime != null">
               create_time=#{createTime},
            </if>
        </set>
   where id=#{id}
   </update>

标签
对集合进行遍历时可以使用该标签。标签有如下属性:
collection:绑定方法参数中的集合,如 List,Set,Map或数组对象
item:遍历时的每一个对象
open:语句块开头的字符串
close:语句块结束的字符串
separator:每次遍历之间间隔的字符串
示例:根据多个文章 id 来删除文章数据。

<delete id="deleteByIds">
   delete from article
   where id in
   //变量:item
    <foreach collection="list" item="item" open="(" close=")" separator=",">
       #{item}
    </foreach>
</delete>
<insert id="batchIn">
        insert into user(
            id,
            username,
            password,
            nickname,
             sex,
            birthday,
            head
        ) values
        <foreach collection="list" item="item" separator=",">
            (
            #{item.id},
            #{item.username},
            #{item.password},
            #{item.nickname},
            #{item.sex},
            #{item.birthday},
            #{item.head}
            )
        </foreach>
    </insert>

在这里插入图片描述

mybatis生成工具…

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值