概述
springmvc
springMVC(接受浏览器发来的请求 + 给浏览器做出响应) spring mybatis(操作数据库 优化jdbc)
springmvc 基于MVC设计模式实现的 实习分层的思想 达到松耦合的目的 提高代码的复用性 扩展性 容错性
M:Model模型,用来封装数据
V:View视图,用来展示数据
C:Controller控制器,用来接受请求和处理响应
工作原理
请求 - 前端控制器(分配谁干活 调度接收请求分发请求) - 映射器处理器(拿请求的路径找到对应的类里的方法)
- 处理器适配器(get方法 返回数据) - 视图解析器(确定用哪一个网页展示数据) - 视图渲染(展示数据)
前端控制器:DispatcherServlet,用来接受请求分发请求
映射器处理器:HandlerMapping,用来根据url找具体的类里的具体方法
处理器适配器:HandlerAdaptor,用来执行方法里的代码
视图解析器:ViewResolver,定位页面的路径
视图:View,用来展示数据
spring
IOC : 是控制反转,指 把创建对象的过程交给了Spring
DI : 是依赖注入,指把对象间的依赖关系 自动维护
AOP : 是补充了OOP的不足
loc
loc 控制反转 @Conponent
不用创建对象 底层是单例模式
将对象Object的创建的权力及对象的生命周期管理过程
管理对象创建和生命周期的机制称为控制反转
方式一:xml
选中resources-右键-new-xml config…-spring config-输入文件名-回车
<bean id="唯一标识" class="类的全路径"></bean>
Map<id的值,class的对象> {hello = new Hello()}
//读取配置文件--参数是文件的路径
ClassPathXmlApplicationContext spring =
new ClassPathXmlApplicationContext("spring-config.xml");
//获取对象--参数是配置文件里bean的id属性值
Object o = spring.getBean("hello");
System.out.println(o);//cn.tedu.spring.Hello@302552ec
Hello h = (Hello) o ;
h.hi();
底层用了反射创建对象
{hello = Class.forName(“cn.tedu.spring.Hello”).newInstance()}
方式二: loc
@Component spring提供
@Service
@Controller
选中resources-右键-new-xml config…-spring config-输入文件名-回车
包扫描:只需要指定从哪个包开始扫描,
用了@Component注解的类,自动ioc
component-scan 包扫描
base-package需要指定一个包的路径
<context:component-scan base-package="cn.tedu.spring2">
</context:component-scan>
@Test
public void ioc2(){
//1,读取核心配置文件
ClassPathXmlApplicationContext spring =
new ClassPathXmlApplicationContext(
"spring-config2.xml");
//2,getBean -- 参数是类名,但是首字母要变成小写才行 User ->user USer ->USer UserIaa ->userIaa
Object o = spring.getBean("user");
System.out.println(o);//cn.tedu.spring2.User@37d4349f
Object o2 = spring.getBean("userInfo");
System.out.println(o2);//cn.tedu.spring2.UserInfo@2805d709
Map<类名首字母要小写 , 类的对象> -{user = new User()}
DI
依赖注入
两个对象之间的依赖关系 可以由框架来完成
类上加@Autowired
通过暴力反射获得目标类里所有的成员变量 谁加@Autowired 就set对象
依赖注入的前提是必须ioc
对象的注入方式
1.构造注入
2.set注入
set注入方式
1.根据类型注入(默认规则)
2.根据名称注入
@Autowired
@Qualifier(value = “id名字”)
这两个注解一块使用
aop
通过通知(Advice)来指定具体做什么事情。
如方法执行前做什么,方法执行后做什么,抛出异常做什么,从而实现对象行为(方法)的增强;
具体通过切点(PointCut)配置切点表达式(expression)
来指定在哪些类的哪些方法上织入(ware)横切逻辑;被切的地方叫连接点(JoinPoint)
实现的效果: 对方法的增强,本质上就是在执行方法的前后添加功能.
经典的使用场景: 统计性能分析 / 权限管理 / 事务管理 / 日志 / 缓存…
好处: 让程序员更专注业务代码本身 不用关心切面中的功能
切面: 本质上就是一个类
通知: 本质上就是一个方法,定义一些功能
分为:前置通知,后置通知和环绕通知,返回后通知,异常通知
前置通知 : 是方法执行前要执行的功能 before 权限 缓存
后置通知 : 是方法执行后要执行的功能 after 关流
环绕通知 : 是方法执行 前 后都要执行的功能 around 统计时间 性能分析
返回后通知 : afterReturning
异常通知 : afterThrowing
切点: 指定哪些类里的哪些方法要用 通知的功能
使用需要导入aop依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
常用AOP注解:
aspectj提供的功能
@Aspect : 表示是一个切面类 由切点和通知组成
@Before : 表示是一个前置通知
@After : 表示是一个后置通知
@Around : 表示是一个环绕通知
@PointCut : 表示切点
package cn.tedu.service;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;@Service //ioc
@Aspect//标记着这是一个aop的类:切面(由切点和切面组成)
public class AopAspect {
//1,切点(指定具体要用通知的类和方法)
//切点表达式:*是通配符 ..表示0~n个
/*哪些类哪些方法要执行我们的功能方法的返回值(通配符 小数,整数都可以)
包的路径 当前包 包括子包里所有类的所有方法 几个返回值都可以*/
//方法返回值/包路径/子包/类名/方法名/参数列表
@Pointcut("execution( * cn.tedu.service..*.*(..))")
public void point(){}
//2,通知(是一个方法自定义功能)
@Around("point()")//是一个环绕通知
public Object doAround(ProceedingJoinPoint joinPoint)
throws Throwable {
long time = System.currentTimeMillis();//计时开始
//去执行你的业务方法--joinPoint连接点
Object o = joinPoint.proceed();
time = System.currentTimeMillis()-time;//计时结束String methodname = joinPoint.getTarget().getClass().getName()//获取类名
+"."+joinPoint.getSignature().getName();//获取方法名System.out.println(methodname+"方法执行时间是: "+time);
return o ;
}
}
mybatis
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。
底层封装了JDBC , 对数据库可以进行操作 , 是一个优秀的持久层框架
好处: 简化了JDBC的开发步骤, 自动完成ORM映射
数据源 连接数据库的方式 在核心配置文件中配置一次即可
核心配置文件
mybatis-config.xml 配置了事务管理,数据源
映射文件
XxxMapper.xml 存放大量的CRUD的SQL语句
核心工具类
会话工厂SqlSessionFactory : 产生会话
会话SqlSession : 执行SQL语句
ORM
是指对象关系映射.
把表里的字段的值 查到 自动交给 类里的属性 保存
xml映射方式
1,准备库,表,数据
修改pom.xml,添加mybatis的jar包
2,创建核心配置文件mybatis-config.xml
mybatis的核心配置文件,配置了事务管理,数据源
environments可以配置多个数据库的连接信息,default指定默认的环境
transactionManager 使用的事务管理器
操作数据库 增删改必须提交事务否则数据库没有任何效果
POOLED 池子 提供连接 用完之后return回池里
为了提高数据库的访问效率 减少创建连接的过程
还需要引入映射文件 必须在</environments>的后面
<mappers>
<mapper resource="UserMapper.xml"></mapper>
</mappers>
3,创建映射文件XxxMapper.xml,写SQL
这个文件是映射文件,写SQL的
namespace用来作为一个mapper.xml文件的唯一标识
id是这条SQL的唯一标识
resultType的值用来封装查到的结果,ORM
4,封装pojo类
属性的名 和 表里的字段名 必须一致,否则无法ORM
5,测试
1,创建SqlSessionFactory对象,线程非安全,用来产生SqlSession
2,创建SqlSession,用来执行sql
3, 定位SQL: namespace的值+id的值
4,解析结果并打印
Resources(专门读取资源文件的)是ibatis包里的
namespace用来作为一个mapper.xml文件的唯一标识
查id=1的用户信息
id是这条SQL的唯一标识
resultType的值用来封装查到的结果,ORM
<select id="getById" resultType="cn.tedu.pojo.User">
select * from user where id=${id}
</select>
查询hanmeimei的,固定语法#{??}用来解析SQL的参数
selectOne
定位SQL(namespace的值.id的值),并执行
selectOne执行查询的SQL,并只会返回一个结果
selectList
定位SQL(namespace的值.id的值),并执行
selectList执行查询的SQL,并返回多个结果
SQL动态获取参数时,可以用#或者$
$ 底层用了低级传输器,可能发生SQL注入攻击,低效,不拼串,可能发生SQL语法错误
# 底层用了高级传输器,安全,高效,会自动拼接字符串 'xiongda'
优化配置
修改核心配置文件,加别名的代码
配置别名,给指定类起一个指定的别名
<typeAliases>
<typeAlias type="cn.tedu.pojo.User" alias="User"></typeAlias>
</typeAliases>
接口映射方式
标准化开发的规则
为了优化定位SQL的字符串拼接过程, namespace的值.id的值
步骤:
0, 创建接口 创建方法
1, namespace的值 是接口的全路径
2, id的值 是接口里的方法名
没有实现类 映射文件充当实现类
接口的全路径=映射文件中namespace的值
接口的方法名=映射文件中id的值
根据接口名称的全路径找到对应的mapper
根据方法名称找到sql语句
把返回值orm交给变量保存
查询结果有多个 用list
mybatis不会自动提交事务,增删改需要自己提交事务
session.commit();
true表示自动提交事务 不需要再写session.commit();
SqlSession session = factory.openSession(true);
动态sql
修改映射文件,实现动态SQL
Mybatis提供使用ognl表达式动态生成sql的功能
利用mybatis框架提供一些标签 完成sql的拼接
常用的标签
sql和include
Sql标签用来提取SQL片段,来提高SQL的复用.
使用位置需要通过include引用指定的SQL片段
<sql id="cols">
id,title,sell_point,price,num,barcode,image,cid,status,created,updated
</sql><select id="find" resultType="Item" parameterType="Item">
SELECT <include refid="cols"/></include>
</select>
if
用来判断 满足条件才拼接sql
执行SQL时,可以添加一些判断条件 不是null才执行
<select id="find" resultType="Item" parameterType="Item">
SELECT <include refid="cols"/> FROM tb_item where
<if test="title != null"> title like #{title} </if>
<if test="dname != null">
where dname=#{dname}</if>
</select>
where
去掉条件中可能多余的and或者or
set
去掉最后可能多余的逗号
foreach
用于in子查询中的多个值的遍历
collection表示要遍历哪种集合里的数据,值是固定值:array/list/Map.key
item表示即将遍历到的数据,separator是分隔符,#{ids}获取遍历到的数据
open="(" close=")" in后面写括号可以不写这个
<delete id="delete">
delete from dept where id in(
<foreach collection="array" item="ids" separator=",">
#{ids}
</foreach>
)
</delete>
parameterType=“int/double等”
指定参数类型,通常制定一个对象类型
用来约束参数的类型 但一般都是自动识别 不常用
当SQL中有特殊字符,mybatis不能正常解析时,
用<![CDATA[ ?? ]]>括起来就解决了 <![CDATA[ and age<=#{age} ]]>
<![CDATA[
and age<=#{age}
]]>
resultType
非常重要的东西,即完成ORM的映射关系所在。
这里指定的cd.tedu.mybatis.domain.User代表把结果集转换成一个User对象实例
resultMap
resultType只能完成简单的ORM,只能完成那些 字段名 和 属性名一致的情况
字段名 和 属性名 不一样的情况,resultType必须换成resultMap,否则无法ORM
resultMap 用于对复杂对象结构时,对应的ResultMap结构名称
字段名和属性名不一样,resultType换成resultMap
ORM:是指把字段的值查到以后 交给 同名属性保存
使用resultMap: 字段名 和 属性名 不一样
id是唯一标识 type是类的全路径(交给那个类处理)
column表里字段名称 propertypojo里对应的属性--表里的那个字段查出来交给那个属性去保存
最强大对象resultMap,结果封装到哪个pojo对象
单独处理 属性名 和 字段名不一致的
<mapper namespace="cn.tedu.dao.UserInfoMapper">
<resultMap id="abc" type="cn.tedu.pojo.UserInfo">
<result column="user_name" property="userName"></result>
</resultMap>
resultMap属性是解决了resultType解决不了的问题,引用指定的resultMap
<select id="selectList" resultMap="abc">
select * from user_info
</select>
</mapper>
优化简化resultmap
在核心配置文件中开启映射的驼峰规则
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
resultMap标签中添加新属性 autoMapping=“true”是开启了自动驼峰规则的匹配
<resultMap autoMapping="true" id="abc" type="cn.tedu.pojo.UserInfo"></resultMap>
多次查询同一个sql语句 是再缓存中查询的
减少和数据库的连接次数 交互次数 减少成本
String StringMVC整合
三层都需要ioc
@SpringBootApplication
SpringBoot 自动配置了包扫描 默认基于启动类所在包 所以resources不需要配置包扫描
控制层 Controller @RestController接受请求 @ResquestMapping做出响应
业务层 Service @Component @Autowired
里面为什么写接口
面向接口编程 程序设计的效果 一个标准 规范
所有功能在接口中定义
持久层 DAO
POJO三层共用(model层)
@Data(lombok)提供 自动生成 get set tostring
@NoArgsConstructor //自动生成无参构造
@AllArgsConstructor//自动生成全参构造
@Accessors(chain = true)//开启链式编程
三大框架整合
添加mybatis的jar包
创建前端的HTML网页
创建启动类RunApp
创建配置文件application.yml
是一个特殊的文件 特殊在这个文件将被springboot框架自动加载
格式非常严格 k:v v在空格后写 空格不可以多也不可以少
开箱即用
mapper-locations:映射文件的位置
classpath:*.xml 根目录下各种xml文件
创建pojo类
创建CarMapper接口
创建映射文件CarMapper.xml
创建CarService接口
创建CarServiceImpl实现类
创建CarController类
注意
/ 是编译后的根目录
maven配置私服镜像
<mirror>
<id>aliyun</id>
<name>aliyun for maven</name>
<mirrorOf>*</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
创建项目之后,不能被maven项目标识
右键pom.xml add as maven project
Server URL地址说明
https://start.spring.io/
https://start.aliyun.com/
父级项目报错
-当spring-boot- starter-parent下面的版本报红时并不是这个版本不存在.
-而是因为idea会默认缓存Maven本地仓库已存在的中的依赖项。
-解决方案就是我们清除一下缓存重新启动
插件版本报错
重启idea 或者添加jar包版本号
jar包下载不完整解决方案:
如果pom.xml文件jar包文件报错. 检查本地仓库中的jar包文件是否完整
如果下载不完整. 则手动删除文件.之后重写下载
jar包传递性的原理
说明: 当maven依赖jar包文件时,首先根据坐标查找本地仓库的路径,之后添加jar包文件
之后再次加载该文件目录的xxx.pom文件.读取其中的依赖项,进行再次依赖.以此类推
jar包下载安全性说明
maven数据传输 通过sha1的数字摘要 包装数据的完整性
SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,
散列值通常的呈现形式为40个十六进制数
如果数据相同,采用相同的hash函数 值是否相同? 相同
常见hash编码 是多少位16进制数?? 8位16进制数
8位16进制数,取值区间多少? 2^32 = (2^4)^8=2^32
00000000-FFFFFFFF
1kb的数据和1gb数据 hash谁快? 一样快
数据相同则hash码相同,hash码相同数据一定相同? 不正确. **hash碰撞!**
不同的数据得到相同的结果
数据的量是有限的 但是需要校验的数据是无限的
降低碰撞概率, 增大hash长度
hash用来加密 人脸识别也运用到hash 抓拍 对比相似度
远程仓库到本地仓库
在远程进行hash计算 当数据下载到本地 需要再次校验
如果2次hash码相同说明数据一致 否则数据被窜改
pom文件
项目坐标 组id/项目名/版本号
可以在本地仓库定位项目
可以作为依赖项被其他项目引用
pojo文件
封装数据 实现序列化接口
implements Serializable
序列化接口作用 保证对象网络传输的有效性
保证数据的完整性 顺序不改变 头还是头 脚还是脚
详细制定了对象编排的规则
parent标签
<!--
父级标签
继承特点: 将父级内容进行引用.(简化)
SpringBoot理解: SpringBoot是框架的框架 整合其他第三方框架
问题: jar包冲突问题严重,之后需要有人统一管理
A.jar ~~~~ 5.1.jar
B.jar ~~~~ 4.8.jar
SpringBoot项目: 官网将大部分框架在内部进行了整合.
并且制定了,统一的版本依赖信息.
parent标签的作用: 定义当前SpringBoot所有依赖的版本号
解决jar包冲突问题
-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/>
</parent>
dependency标签
<!--按需导入
历史说明: 2010 原来SSM 需要手动的编辑大量的的配置文件
思想: SpringBoot使用体现了"开箱即用"的思想
jar包不加标签因为在父级进行了统一定义
-->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<!--Springboot的启动器 在内部已经将整合的配置写好,实现拿来就用-->
<artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
build标签作用
<!--build标签
springboot项目在打包部署发布时,需要依赖maven工具API
如果不添加该插件,则直接影响项目发布
如果没有build标签则项目打包之后不能正常执行
没有主清单属性 里面没有可运行的main方法
-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.3</version>
</plugin>
</plugins>
</build>
Maven指令
1.clean 删除编译后的目录 target .java 文件源码 .jar包(xxx.class文
件)
- 用法: 1.当可能出现编译问题时 使用clean. 2.项目打包前使用
2.install 项目发布 将xxx.class文件 打包成为 xxx.jar
-jar包位置: 1.target目录下 2.本地仓库中.
java项目发布命令
http 简洁 不安全 容易被拦截
https 有证书 用户的访问不受攻击 不容易被拦截
进入jar包根目录 输入cmd
项目发布命令 java -jar xxx.jar
如果项目发布成功之后,需要关闭. 则直接关闭dos命令窗口即可.
如果依然不能正常关闭.则杀死进程/或者重启计算机.
找到服务 根据PID号结束进程
dos命令窗口锁死
ctrl + c 万能取消指令
跳过测试类打包
说明: maven执行打包命令时, 默认条件下,会执行测试类中的方法.
并且这些方法都要执行. 隐患 可能某些测试方法由于种种原因 执行报错. 则install的操作执行失败.
矛盾点: 项目打包与test类之间的问题.
解决方案: 要求install时 不要执行test方法,
<properties>
<!--指定JDK版本-->
<java.version>1.8</java.version>
<!--跳过测试类打包-->
<skipTests>true</skipTests>
</properties>
properties文件为属性赋值
业务有时会需要动态赋值,如果将大量的业务数据写到yml文件中 导致代码混乱.最好的方式应该指定properties文件 为业务赋值
#语法:
#数据结构: key=value
#注意事项: 不要添加""号 本身就是字符串.
#字符集编码: 写法采用utf-8,程序读取时采用ISO-8859-1 pro.msg=配置信息
动态为属性赋值
package com.jt.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController //将该类交给Spring管理
//spring负责加载指定的配置文件
//如果注解中只有一个属性名称为value 则可以省略不写
@PropertySource(value="classpath:/msg.properties",encoding = "utf-8")
public class HelloController {/**
* 规则:
* 1. 当Spring容器启动时,会加载YML配置文件.
* 会将内部的key-value结构 加载到spring维护的内存空间中
* 2. @Value功能,从spring容器中根据key 动态赋值
* 3. springel表达式 简称:spel
*
* 使用场景:
* 如果代码中需要给成员变量赋值时,一般采用动态赋值的方式.
*/
@Value("${msg.hello}")
private String msg;
@Value("${pro.msg}")
private String proMsg;
@RequestMapping("/hello")
public String hello(){return msg+"||"+proMsg;
}
}
环境切换
不管是几个环境,要求配置项都必须相同,值可以不同
语法:
1.使用—实现YML配置文件的分割
2.定义环境名称
3.定义默认环境名称
#指定默认的环境
spring:
profiles:
active: test
---#关于YML配置文件说明
# 1.数据结构 key=value
# 2.数据类型 默认都是字符串 如果需要类型转化,则框架已经在内部完成
# 3.yml写法: 1.key: (空格)value 2.有层级结构 编辑时注意
# 4.字符集编码: 默认程序加载时都是UTF-8
#定义环境名称
spring:
config:
activate:
on-profile: devserver:
port: 8080
#项目发布的路径
servlet:
# /缺省值 localhost:8080/jt/xxxx请求路径
context-path: /#2.为属性赋值 hello代表前缀 key=hello.msg
hello:
msg: "我喜欢开发"#环境分割线
---
spring:
config:
activate:
on-profile: testserver:
port: 8090
#项目发布的路径
servlet:
# /缺省值 localhost:8080/jt/xxxx请求路径
context-path: /#2.为属性赋值 hello代表前缀 key=hello.msg
hello:
msg: "我喜欢测试"
最后
以上就是搞怪冬日为你收集整理的框架...springmvcspringmybatis String StringMVC整合 三大框架整合 注意pom文件properties文件为属性赋值 环境切换 的全部内容,希望文章能够帮你解决框架...springmvcspringmybatis String StringMVC整合 三大框架整合 注意pom文件properties文件为属性赋值 环境切换 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复