java小白第八天之SSM
写在前面
本文是边看黑马b站视频边写的一片笔记, 文中大多图片都来自黑马视频. 旨在巩固学习以及方便后续查阅和供广大朋友们学习, 感谢黑马视频分享
01 Spring
02 初识 Spring
02 spring framework 系统架构
03 核心容器
01 IOC 入门案例
02 DI 入门案例
03 bean配置
04 bean 实例化
05 bean的生命周期
06 依赖注入
01 setter注入引用类型
02 setter注入简单类型和字符串
03 constructor注入数据
对于 constructor 注入, 由于根据参数名注入对应数据, 容易发生代码耦合, 针对代码耦合情况, 有几种不同方式的处理方案
07 依赖自动装配
08 集合注入
09 案例
10 加载 properties
11 容器
01 创建容器的两种方式
02 获取 bean 的三种方式
03 容器类层次结构图
12 核心容器总结
04 注解开发
@Component 注解 注入bean到容器中, 记得在spring配置文件中添加Component包扫描
java类替换spring配置文件 @Configuration
01 bean 管理
02 依赖注入
03 第三方bean管理
创建一个方法,使用注解 @Bean
将方法的返回值作为 Bean 注入到spring容器中
使用注解 @Bean 注明该方法的返回值需要注入容器中成为一个Bean
总结
Spring 整合 Mybatis
所以 spring 管理的bean是 SqlSessionFactory
package com.it.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
public class MyBatisConfig {
/**
* 注入 SqlSessionFactory 使用 mybatis-spring 提供的 SqlSessionFactoryBean
* @param dataSource
* @return
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
// ssfb.setTypeAliasesPackage("com.it.pojo");
ssfb.setDataSource(dataSource);
return ssfb;
}
/**
* 注入 mybatis 配置文件中 mapper 标签
* @return
*/
@Bean
public MapperScannerConfigurer mapperScannerConfigurer(){
MapperScannerConfigurer msc = new MapperScannerConfigurer();
msc.setBasePackage("com.it.dao");
return msc;
}
}
07 Spring 整合 Junit
代码示例
package com.it.service;
import com.it.config.SpringConfig;
import com.it.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) // 注明 spring 测试 设定专用的类运行器
@ContextConfiguration(classes = SpringConfig.class) // 注明 spring 核心配置类的位置
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testSelectByID(){
User user = userService.selectByID(2);
System.out.println(user);
}
}
pom.xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.16.RELEASE</version>
</dependency>
08 Spring AOP
本质:代理模式
01 AOP简介
02 AOP 入门案例
AOP入门案例步骤:
一
二
三
四
五
六
七
代码示例
# 通知类与通知
package com.it.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
// 通知类
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.it.dao.BrandDao.update())")
private void aop(){};
@Before("aop()")
// 共性功能 通知
public void method(){
System.out.println(System.currentTimeMillis());
}
}
# springConfig
package com.it.config;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan("com.it")
@EnableAspectJAutoProxy // 启动 aspect aop 自动代理
//@PropertySource("jdbc.properties")
//@Import({JDBCConfig.class, MyBatisConfig.class})
// 导入 jdbc(dataSource)配置类 也可在该类加 @Configuration 注解,但需要包扫描注解@ComponentScan扫描到该类所在包
public class SpringConfig {
}
# 连接点
package com.it.dao.impl;
import com.it.dao.BrandDao;
import org.springframework.stereotype.Repository;
@Repository
public class BrandDaoImpl implements BrandDao {
public void save(){
System.out.println(System.currentTimeMillis());
System.out.println(" book dao save ... ");
}
public void update(){
System.out.println("book dao update...");
}
}
03 AOP 工作流程
04 AOP 切入点表达式
05 AOP 通知类型
06 AOP 案例
06 AOP 通知获取数据
参数获取
代码示例
package com.it.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
// 通知类
@Component
@Aspect
public class MyAdvice {
@Pointcut("execution(void com.it.dao.BrandDao.update())")
private void aop(){};
@Before("aop()")
// 共性功能 通知
public void method(){
System.out.println(System.currentTimeMillis());
}
@Pointcut("execution(* com.it.dao.*Dao.findNameByID(..))")
private void daoPt(){}
@Before("daoPt()")
public void before(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs(); // 获取参数,其他通知类型方法也一样
System.out.println("before advice ...");
}
@After("daoPt()")
public void after(){
System.out.println("after advice ...");
}
// 环绕通知需要返回原方法的返回值,所以环绕通知的方法的返回值类型需为 Object
// 并在方法最后将其返回
// 可以获取返回值
// 可以获取异常
@Around("daoPt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
args[0] = 10000000;
Object proceed = pjp.proceed(args);
return proceed;
}
// 可以获取返回值
// JoinPoint 位于第一个参数
@AfterReturning(value = "daoPt()", returning = "ret")
public void afterReturning(JoinPoint joinPoint, Object ret){
System.out.println("afterReturning advice ...");
}
// 可以获取异常
// JoinPoint 位于第一个参数
@AfterThrowing(value = "daoPt()", throwing = "throwable")
public void afterThrowing(JoinPoint joinPoint, Throwable throwable){
System.out.println("afterThrowing advice ...");
}
}
07 案例 – 百度网盘密码数据兼容处理
AOP 总结
09 Spring 事务
01 Spring 事务注解开发
添加spring 事务的步骤
- 需要开启事务处添加注解
@Transactional
- 在JDBC配置中事务管理器类
- 在spring核心配置类添加注解
@EnableTransactionManagement
开启spring注解事务
02 Spring 事务角色
03 事务相关配置
案例事务分析
对于日志记录事务需要开启独立事务,而两个转账事务需要加入业务层事务,这种事务需要加入还是独立开启自己事务的行为称为事务传播行为
事务传播行为: 事务协调员对事务管理员所携带事务的处理态度
代码示例
# 业务类
package com.it.service.impl;
import com.it.dao.AccountDao;
import com.it.dao.LogDao;
import com.it.service.AccountService;
import com.it.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private LogService logService;
/**
*
* @param out 转出方
* @param in 转入方
* @param money 金额
*/
public void transMoney(String out, String in, Double money) {
boolean flag = false;
/**
* 记录转账日志, 不管转账是否成功, 都需要记录相应日志
* try中转出和转入事务加入事务管理员事务
* 日志记录事务单独开启新的事务
*/
try {
accountDao.outMoney(out,money);
int i = 1/0;
accountDao.inMoney(in,money);
flag = true;
} finally {
logService.insertLog(out,in,money,flag);
}
}
}
# 日志记录业务类事务独立
package com.it.service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public interface LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
void insertLog(String out, String in, Double money, boolean flag);
}
02 SpringMVC
SpringMVC 也是 Spring 的一部分
表现层开发
SpringMVC 与 Servlet 技术功能等同, 都是 web 层开发技术
01 SpringMVC简介
01 SpringMVC概述
02 SpringMVC 入门案例
Spring-webmvc包包含
![v!v](https://img-blog.csdnimg.cn/153c67ae727e46f5ac4c87db520ed85d.png)
代码示例
package com.it.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
// Servlet 容器的初始化类, 加载 SpringMVC 配置文件到 Servlet 容器中
public class ServletContainInitialConfig extends AbstractDispatcherServletInitializer {
// 加载 SpringMVC 配置
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
webApplicationContext.register(SpringMVCConfig.class);
return webApplicationContext;
}
// 设置哪些请求归属SpringMVC处理
protected String[] getServletMappings() {
return new String[]{"/"}; // 表示所有请求都由SpringMVC处理
}
// 加载 Spring 容器配置
protected WebApplicationContext createRootApplicationContext() {
return null;
}
}
03 SpringMVC 与 Spring 加载Bean控制
Controller包下的类需要加载到SpringMVC中, 由SpringMVC控制
Service dao 等层的Bean需要加载到Spring容器中, 由Spring控制
上面Bean加载的简化形式, 换个子类
04 PostMan
自行摸索使用
02 请求与响应
01 请求
请求映射路径
01 各类型数据传参
普通请求参数接收
Post请求参数乱码问题
所有参数
代码示例
package com.it.controller;
import com.it.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("/user")
public class UserController {
// 请求参数名与形参名一致
@RequestMapping("/save")
@ResponseBody
public String save(String name){
System.out.println(name);
return "张三";
}
// 请求参数名与形参名不一致
// 使用注解 绑定 请求参数与形参关系 @RequestParam
@RequestMapping("/save1")
@ResponseBody
public String save1(@RequestParam("username") String name){
System.out.println(name);
return "张三";
}
/**
* 请求参数为POJO
* 请求参数是 User 属性, springMVC 则自动封装进 user 对象
* 即,当请求参数与user属性名不一致时,或部分一致时, 只封装对应的请求参数进user对象
*/
@RequestMapping("/save2")
@ResponseBody
public String save2(User user){
System.out.println(user);
return "张三";
}
/**
* 请求参数为嵌套POJO -- 即 user类的成员属性是引用类型
* 请求参数格式为 引用类型.属性名 封装进对应引用类型的属性
* User{username='null', age=null, address=Address{name='北京', num=null}}
*/
@RequestMapping("/save3")
@ResponseBody
public String save3(User user){
System.out.println(user);
return "张三";
}
/**
* 请求参数为数组
* 请求参数格式为 数组参数名 值即为值
*
*/
@RequestMapping("/save4")
@ResponseBody
public String save4(String[] num){
System.out.println(num);
return "张三";
}
/**
* 请求参数为集合
* 请求参数格式为 集合参数名 值即为值
* 需要使用注解 @RequestParam 告诉 SpringMVC 此时是使用集合接收参数, 不是创建一个引用对象, 封装为其属性
* [1, 张三]
*/
@RequestMapping("/save5")
@ResponseBody
public String save5(@RequestParam List<String> list){
System.out.println(list);
return "张三";
}
}
02 JSON 数据传参
三大步骤
涉及两个注解
代码示例
package com.it.controller;
import com.it.pojo.User;
import org.springframework.expression.EvaluationException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/**
* 接收json数据
* 1. 导坐标
* 2. 开启注解 @EnableWebMvc
*/
@Controller
@RequestMapping("/json")
public class JSONController {
// 集合参数: json格式 ["xxx","xxx"]
// 参数:["张三","abc","12\"34"]
// 输出: [张三, abc, 1234]
@RequestMapping("/json1")
@ResponseBody
public String json1(@RequestBody List<String> list){
System.out.println(list);
return "json1";
}
// pojo: json格式
// {
// "key":value,
// "key":value
// }
// 参数:{
// "username":"张三",
// "age":20,
// "address":{
// "name":"北京",
// "num":33
// }
//}
// 输出:User{username='张三', age=20, address=Address{name='北京', num=33}}
@RequestMapping("/json2")
@ResponseBody
public String json2(@RequestBody User user){
System.out.println(user);
return user.toString();
}
// 集合引用类型: json格式
// [
// {
// "key":value,
// "key":value
// },
// {
"key":value,
"key":value
},
// ]
// 参数:[
// {
// "username":"张三",
// "age":20,
// "address":{
// "name":"北京",
// "num":33
// }
//},
//{
// "username":"张三2",
// "age":20,
// "address":{
// "name":"北京2",
// "num":33
// }
//}
//]
// 输出: [User{username='张三', age=20, address=Address{name='北京', num=33}},
// User{username='张三2', age=20, address=Address{name='北京2', num=33}}]
@RequestMapping("/json3")
@ResponseBody
public String json3(@RequestBody List<User> user){
System.out.println(user);
return user.toString();
}
}
03 接收日期参数
02 响应
注解说明
03 REST
01 REST简介
02 示例
03 Rest 简化开发
简化目标
04 拦截器
01 概念
02 入门案例
也可以直接在SpringMvc配置类中写
03 拦截器处理方法中的参数
04 拦截器链的执行
拦截器的执行顺序与配置中添加的拦截器顺序一致
当某个拦截器的预处理返回false时,相应的后续执行会终止,具体如图
03 SSM整合
01 SSM技术整合
SSM整合流程
1. 创建工程
2. SSM整合
1. Spring
+ SpringConfig
2. MyBatis
+ MybatisConfig
+ JdbcConfig
+ Jdbc.properties
3. SpringMVC
+ ServletConfig
+ SpringMvcConfig
3. 功能模块
1. 表与实体类
2. dao(接口+自动代理)
3. service(接口+实现类)
+ 业务层接口测试(整合 JUnit)
4. controller
+ 表现层接口测试(Postman)
02 表现层数据封装
03 异常处理
01 异常处理思想
异常处理
- 分类处理
- 在表现层处理
- 使用 AOP 思想处理
- Spring 提供了实现类
异常类型
异常交给表现层处理
异常怎么处理
Spring提供实现类
代码示例
- Spring 提供了实现类
package com.it.exception;
import com.it.vo.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 异常处理器
* + 处理controller层出现的异常,
* controller层出现异常之后,直接被该类的doException方法捕捉,之后走该方法中的逻辑,不再走controller后续代码
*/
@RestControllerAdvice // 使用 Rest 风格
//@ControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler({Exception.class})
public Result doException(Exception e){
return new Result(666,null,"报异常了哦");
}
}
02 项目异常处理方案
项目异常具体分为3类
异常处理步骤
代码示例
# controller
@GetMapping("/{id}")
public Result getById(@PathVariable("id") Integer id) {
// 业务异常
if (id<0){
throw new BusinessException(Code.Business_ERR,"id非法");
}
// 系统异常
if (id==1){
try{
int i = 1/0;
}catch (Exception e){
throw new SystemException(Code.System_ERR,"系统异常",e);
}
}
// 其他异常
if (id==2){
int[] arr = new int[5];
arr[8] = 0;
}
Book book = bookService.getById(id);
Integer code = book != null ? Code.SELECT_OK : Code.SELECT_ERR;
String msg = book != null ? "success" : "error";
return new Result(code,book,msg);
}
# ProjectException
package com.it.exception;
import com.it.vo.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 异常处理器
* + 处理controller层出现的异常,
* controller层出现异常之后,直接被该类的doException方法捕捉,之后走该方法中的逻辑,不再走controller后续代码
*/
@RestControllerAdvice // 使用 Rest 风格
//@ControllerAdvice
public class ProjectExceptionAdvice {
// 处理系统异常
@ExceptionHandler(SystemException.class)
public Result doSystemException(SystemException e){
// 记录日志
// 发送消息给运维
// 发送邮件给开发人员, 发送 e 给开发人员
return new Result(e.getCode(),null,e.getMessage());
}
// 处理业务异常
@ExceptionHandler(BusinessException.class)
public Result doBusinessException(BusinessException e){
return new Result(e.getCode(),null,e.getMessage());
}
// 处理其他异常
@ExceptionHandler({Exception.class})
public Result doException(Exception e){
return new Result(666,null,"报异常了哦");
}
}
03 SSM 整合开发页面表格案例
04 Maven
01 分模块开发
每一个模块需要运行maven中的install命令,将其打成jar包,放入仓库中,才能被其他模块使用
02 依赖管理
依赖传递
查看使用的依赖版本
可选依赖
排除依赖
03 继承与聚合
聚合
继承
04 属性
01 资源文件中引用 pom 文件属性
02 其他属性
03 版本管理
05 多环境配置和应用
01 多环境配置
02 跳过测试
06 私服
01 nexus
02 私服操作流程
03 私服资源的上传与下载
私服资源的上传与下载是和本地仓库直接联系的,即是由本地仓库访问私服,执行资源的下载与上传,所以访问私服的相关配置,应该写在本地仓库中
配置本地仓库设置文件
在pom中配置保存jar包的私服地址
<!-- 阿里云镜像仓库 -->
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
04 SpringBoot
01 SpringBoot 简介
原始SpringMvc开发过程
![v!v](https://img-blog.csdnimg.cn/4f1a51e11c904f15953f087329405cd1.png)
springboot 项目快速搭建
Spring程序与boot程序对比
前后端分离开发
02 基础配置-配置文件
01 yml
02 多环境配置
多环境启动命令格式
03 多环境开发控制
当maven和spring都配置多环境时,听谁的???
MAVEN
maven控制版本,spring加载maven中配置版本
04 配置文件分级
03 SpringBoot 整合第三方技术
01 SpringBoot 整合 Junit
02 SpringBoot 整合 Mybatis