定西市建设网站费用,湖南响应式网站设计,搜索引擎营销图片,舆情分析网站JavaWeb 前端Web开发javaScript1.JS引入2.JS基础语法3.JS函数4.JS对象 BOMDOM文档对象模型JS事件监听VueVue常用指令Vue的生命周期 AjaxAxios 前端工程化环境准备NodeJS安装和Vue-cli安装vue项目Vue组件库Element组件的使用 Vue路由Nginx打包部署 后端Web开发MavenSpringBootHT… JavaWeb 前端Web开发javaScript1.JS引入2.JS基础语法3.JS函数4.JS对象 BOMDOM文档对象模型JS事件监听VueVue常用指令Vue的生命周期 AjaxAxios 前端工程化环境准备NodeJS安装和Vue-cli安装vue项目Vue组件库Element组件的使用 Vue路由Nginx打包部署 后端Web开发MavenSpringBootHTTP协议请求数据格式响应数据格式协议解析 Web服务器请求响应请求参数的接收响应 分层解耦IOCDI入门IOC详解DI详解 MySQLSQL数据库设计 多表设计1对多1对1多对多 多表查询连接查询内连接外连接左外连接右外连接 子查询事务索引 MyBatisJDBC数据库连接池lombok工具包基础操作配置mybatis日志预编译SQL新增主键返回 数据封装XML映射文件动态查询批量操作 登录认证会话技术 登录校验JWT令牌过滤器Filter过滤器链登录校验Filter 拦截器Interceptor 异常处理全局异常处理器 Spring事务管理事务属性回滚事务传播行为案例 AOP基础案例 Web后端总结 前端Web开发
HTML负责网页的结构页面元素和内容。 CSS负责网页的表现页面元素的外观、位置等页面样式如颜色、大小等。
javaScriptJs脚本语言。用来控制网页行为的它能使网页交互。交互效果
javaScript
1.JS引入
!-- 内部脚本 --
scriptalert(Hello JS)
/script!-- 外部脚本 --
script srcjs/demo.js/script2.JS基础语法 JS输出语句
script
//方式一: 弹出警告框
window.alert(hello js);//方式二: 写入html页面中
document.write(hello js);//方式三: 控制台输出,在console可以看到
console.log(hello js);
/scriptJS变量
var var声明的变量可以接受任何数据类型的值变量可以多次赋值后面值把前面覆盖 var声明的变量的作用于是全局的
script//var定义变量var a 10;a 张三;alert(a);var a 20;alert(a);
/scriptlet 局部变量不能重新定义 script{let x 1;x 2;alert(x);}/scriptconst 常量不能重新定义不能多次赋值
3.JS函数
script//定义函数function add(a,b){return a b;}//函数调用var result add(10,20);alert(result);
/script4.JS对象
Array
特点长度可变类型可变
script//定义数组var arr new Array(1,2,3,4);console.log(arr[0]);arr[10] 50;for (let i 0; i arr.length; i) {console.log(arr[i]);}//forEach遍历数组中有值的元素arr.forEach(function(e) {console.log(e)});//push添加元素到数组尾部arr.push(7,8,9);console.log(arr);//splice删除元素arr.splice(2,2) //从数组下标为2开始删删2个console.log(arr);
/scriptString
script//定义字符串var str Hello;
/script自定义对象
script//自定义对象var user {name:Tom,age:20,gender:male,eat: function(){alert(用膳);}};//获取对象中的属性console.log(user.name);//对象中方法的调用user.eat();
/scriptJSON
作为数据的载体在网络中传输。
json必须使用双引号
script//定义jsonvar jsonstr {name:Tom, age:18, addr:[北京,上海,西安]};alert(jsonstr.name) //结果为undefined因为jsonstr是一个字符串要是一个对象才可以//json字符串--js对象var obj JSON.parse(jsonstr);alert(obj.name)//js对象--json字符串var jsonStr JSON.stringify(jsonstr);
/scriptBOM
浏览器对象模型运行JavaScript与浏览器对话JavaScript将浏览器的各个部分封装为对象
BOM中提供了5个对象 主要学习下面两个对象 window浏览器窗口对象
script//BOM//window//获取window可以省略window.alert(Hello BOM);//方法//confirm - 对话框var flag window.confirm(你确认删除该记录吗);alert(flag);//定时器 - setInterval -- 周期性的执行某个函数var i 0;setInterval(function(){iconsole.log(定时器执行了i次)})//定时器 - srtTimeout --延迟指定时间执行一次setTimeout(function(){alert(JS)},3000);
/scriptlocation地址栏对象
script//location地址栏对象alert(location.href)location.href https://www.baidu.com/index.htm
/scriptDOM文档对象模型
将 HTML 文档的各个组成部分封装为对象
获取DOM中的元素对象Element对象 也就是标签 操作Element对象的属性标签的属性
bodyimg idh1 srcimg/off.gif brbrdiv classcls教育/div brdiv classcls程序员/div brinput typecheckbox namehobby 电影input typecheckbox namehobby 旅游input typecheckbox namehobby 游戏
/bodyscript//1. 获取Element元素//1.1 获取元素-根据ID获取var img document.getElementById(h1);alert(img);//1.2 获取元素-根据标签获取 - divvar divs document.getElementsByTagName(div);for (let i 0; i divs.length; i) {alert(divs[i]);}//1.3 获取元素-根据name属性获取var ins document.getElementsByName(hobby);for (let i 0; i ins.length; i) {alert(ins[i]);}//1.4 获取元素-根据class属性获取var divs document.getElementsByClassName(cls);for (let i 0; i divs.length; i) {alert(divs[i]);}//2. 查询参考手册, 属性、方法var divs document.getElementsByClassName(cls);var div1 divs[0];div1.innerHTML 英才教育;/scriptJS事件监听
事件发生在HTML元素上的 “事情”
事件绑定 scriptfunction on(){alert(按钮1被点击了...)}document.getElementById(btn2).onclick function(){alert(按钮2被点击了...);}/script常见事件
Vue
前端js框架
Vue快速入门
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleVue-快速入门/titlescript srcjs/vue.js/script
/head
bodydiv idappinput typetext v-modelmessage{{message}}/div/body
script//定义Vue对象new Vue({el: #app, //vue接管区域data:{message: Hello Vue}})
/script
/htmlVue常用指令
v-bind、v-model、v-on、v-if、v-show、v-for
Vue的生命周期
主要掌握mounted挂载完成
Ajax
与服务器进行数据交互
异步交互可以在不重新加载整个页面的情况下与服务器交换数据并更新部分网页的技术。
Axios
前端工程化
环境准备
Vue-dli是官方提供的一个脚手架用于快速生成Vue的项目模板
Vue-cli主要提供了如下功能 统一的目录结构 本地调试 热部署 单元测试 集成打包上线
环境依赖NodeJS
NodeJS安装和Vue-cli安装
先下NodeJS再去下Vue-cli NodeJS下载地址 https://nodejs.org/en
Vue-cli安装 使用管理员身份运行命令行在命令行中执行如下指令 npm install -g vue/cli
vue项目 Vue组件库Element
安装ElementUI的组件库 npm i element-ui -S
Vue项目开发流程 组件的使用
官方文档https://element.eleme.cn/#/zh-CN/component/installation
button 按钮 Table 表格 Pagination分页 Dialog对话框 Form表单
Vue路由 Nginx打包部署
需要安装Nginx nginx默认占用80要改端口
后端Web开发
Maven
用于管理和构建java项目的工具
依赖管理统一项目结构项目构建
SpringBoot
HTTP协议
超文本传输协议规定了浏览器和服务器之间数据传输的规则
特点 基于TCP协议面向连接安全 基于请求-响应模型一次请求对应一次响应 HTTP是无状态协议对于事物处理没有记忆能力。每次请求-响应都是独立的
优点速度快 缺点多次请求间不能共享数据
请求数据格式 响应数据格式 协议解析
Web服务器
一个软件程序对HTTP协议的操作进行封装让Web开发更加快捷。
主要功能提供网上信息的浏览服务
请求响应 请求参数的接收
简单参数
实体参数
数组集合
json
路径参数
响应 分层解耦
三层架构 复用性强、便与维护、利于扩展 内聚软件中各个功能模块内部的功能关系 耦合衡量软件中各个层/模块之间的依赖、关联的程度 软件设计原则高内聚低耦合
控制反转IOC对象的创建控制权由程序自身转移到外部容器 依赖注入DI容器为应用程序提供运行时所依赖的资源称之为依赖注入 Bean对象IOC容器中创建、管理的对象
IOCDI入门
1.Service层及Dao层的实现类交给IOC容器管理。 加Component注解
2.为Controller及Service注入运行时依赖对象。 加Autowired注解
3.运行测试。
IOC详解 Bean组件扫描 默认扫描范围是启动类所在包及其子包 通过在启动类中加ComponentScan({“dao”,“com.itheima”})可以修改
DI详解
MySQL MySQL数据模型 关系型数据库建立在关系模型基础上由多张相互连接的二维表组成的数据库。
SQL
SQL操作关系型数据库的编程语言
SQL语句通常分为4大类我们主要学前面3个 DDL数据定义语言 DML数据操作语言 DQL数据查询语言 DCL数据控制语言
数据库设计
DDL 数据库操作
表操作 创建
约束作用于表中字段上的规则用于限制表中的数据
DQL 基础查询 select 字段列表 from 表名列表
条件查询 where 条件列表
分组查询 group by 分组字段 having 分组之后的条件
排序查询 order by 排序字段列表
分页查询 limit 分页参数
多表设计
在进行数据库表设计时会根据业务需求及业务模块之间的关系分析并设计表结构由于业务之间相互关联所以各个表结构之间也存在各种联系。
1对多
在数据库表中多的一方添加字段来关联1的一分的主键
1对1
在任意一方加入外键关联另外一方的主键并且设置外键为唯一的UNIQUE
多对多
建立第三张中间表中间表至少包含两个外键分别关联两方主键
案例
多表查询
在做多表查询时需要消除无效的笛卡尔积
连接查询
内连接
-- 内连接
-- A. 查询员工的姓名 , 及所属的部门名称 (隐式内连接实现)
select tb_emp.name,tb_dept.name from tb_emp,tb_dept where tb_emp.dept_id tb_dept.id;-- B. 查询员工的姓名 , 及所属的部门名称 (显式内连接实现)
select tb_emp.name,tb_dept.name from tb_emp inner join tb_dept on tb_emp.dept_id tb_dept.id;外连接
左外连接
查询左表所有数据包含两表交集部分数据
右外连接
查询右表所有数据包含两表交集部分数据
-- 外连接
-- A. 查询员工表 所有 员工的姓名, 和对应的部门名称 (左外连接)
select tb_emp.name,tb_dept.name from tb_emp left join tb_dept on tb_emp.dept_id tb_dept.id;-- B. 查询部门表 所有 部门的名称, 和对应的员工名称 (右外连接)
select tb_emp.name,tb_dept.name from tb_emp right join tb_dept on tb_emp.dept_id tb_dept.id;子查询
-- 标量子查询
-- A. 查询 教研部 的所有员工信息
-- a.先查教研部的部门ID - tb_dept
select id from tb_dept where name 教研部;
-- b.再查该部门ID下的员工信息
select * from tb_emp where dept_id (select id from tb_dept where name 教研部);-- 列子查询
-- A. 查询 教研部 和 咨询部 的所有员工信息
select id from tb_dept where name 教研部 or name 咨询部;
select * from tb_emp where dept_id in (select id from tb_dept where name 教研部 or name 咨询部);-- 行子查询
-- A. 查询与 韦一笑 的入职日期 及 职位都相同的员工信息 ;
select entrydate,job from tb_emp where name 韦一笑;select * from tb_emp where (entrydate,job) (select entrydate,job from tb_emp where name 韦一笑);-- 表子查询
-- A. 查询入职日期是 2006-01-01 之后的员工信息 , 及其部门信息
select * from tb_emp where entrydate 2006-01-01;select e.*,tb_dept.name from (select * from tb_emp where entrydate 2006-01-01) e ,tb_dept where e.id tb_dept.id;事务
一组操作的集合。事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求及这些操作要么同时成功或者失败。
四大特征 原子性、一致性、隔离性、持久性
-- 事务
-- 开启事务
start transaction ;-- 删除部门
delete from tb_dept where id 4;
-- 删除部门下的员工
delete from tb_emp where dept_id 4;-- 提交事务
commit ;-- 上面如果有个操作失败回滚事务
rollback ;select * from tb_dept;
select * from tb_emp;索引
物理的对数据库表中一列或多列的值进行排序的一种存储结构帮助数据库高效获取数据。 -- 索引
-- 创建
create index idx_emp_name on tb_emp(name);-- 查询
show index from tb_emp;-- 删除
drop index idx_emp_name on tb_emp;MyBatis
持久层框架支持自拟定SQL、存储过程以及高级映射。
MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。
让idea对sql语句有提示 JDBC
使用java语言操作关系型数据库的一套API应用程序编程接口
数据库连接池
数据库连接池是个容器负责分配、管理数据库连接
标准接口DataSource
lombok工具包
是一个实用的java类库能通过注解的形式自动生成构造器并可以自动化生成日志变量简化java开发
基础操作
配置mybatis日志
#配置mybatis日志,输出到指定控制台
mybatis.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImpl控制台输出 Preparing: delete from mybatis.emp where id ?Parameters: 15(Integer)Updates: 1预编译SQL
性能更强、更安全防止sql注入
sql注入通过操作输入的数据来修改事先定义的SQL语句以达到执行代码对服务器进行攻击的方法。
sql注入案例 因为是复制的jar包所以要修改jar包中数据库配置信息 解压 jar包命令 jar -xvf [jar包名称] 如下结构 │ xxx.jar │ └─BOOT-INF └─classes application.yml 修改application.yml后 增量更新命令 jar -uvf0 xxx.jar BOOT-INF
没有采用预编译的jar 采用预编译的jar
Mybatis中 delete from mybatis.emp where id ?{id} ?{id}是拼接符会直接把值拼接到sql语句中
delete from mybatis.emp where id #{id} #{id}就是预编译执行sql时将#{id}替换为生成预编译sql会自动设置参数值
新增主键返回
Options(keyProperty id,useGeneratedKeys true) //会自动将生成的主键值赋给emp对象的id属性数据封装
实体类属性名和数据库表查询返回的字段名一致mybatis会自动封装
对于不一致的推荐在配置中开启mybatis的驼峰命名自动映射开关
#开启mybatis的驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-casetrue模糊查询 name like ‘%${name}%’
推荐这样写 name like concat(‘%’,#{name},‘%’)
XML映射文件
一些简单的增删改查功能推荐使用Mybatis注解。 如果需要实现复杂的SQL功能建议使用XML来配置映射语句。 官方文档地址 https://mybatis.net.cn/getting-started.html
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd动态查询
随着用户的输入或外部条件的变化而变化的SQL语句 sql idcommonSelectselect id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom emp/sql!-- 动态更新员工--update idupdate2update empsetif testusername ! nullusername #{username},/ifif testname ! nullname #{name},/ifif testgender ! nullgender #{gender},/ifif testimage ! nullimage #{image},/ifif testjob ! nulljob #{job},/ifif testentrydate ! nullentrydate #{entrydate},/ifif testdeptId ! nulldept_id #{deptId},/ifif testupdateTime ! nullupdate_time #{updateTime}/if/setwhere id #{id}/update!-- 查询员工 --!--resultType: 单条记录封装的类型--select idlist resultTypecom.itheima.pojo.Empinclude refidcommonSelect/whereif testname ! nullname like concat(%, #{name}, %)/ifif testgender ! nulland gender #{gender}/ifif testbegin ! null and end ! nulland entrydate between #{begin} and #{end}/if/whereorder by update_time desc/select//动态条件查询public ListEmp list(String name, Short gender, LocalDate begin , LocalDate end);//动态更新员工public void update2(Emp emp);批量操作 !--批量删除员工 (12,13,14)--!--collection: 遍历的集合item: 遍历出来的元素separator: 分隔符open: 遍历开始前拼接的SQL片段close: 遍历结束后拼接的SQL片段--delete iddeleteByIdsdelete from emp where id inforeach collectionids itemid separator, open( close)#{id}/foreach/delete//批量删除员工public void deleteByIds(ListInteger ids);登录认证
会话技术
会话用户打开浏览器访问web服务器资源会话建立直到有一方断开连接会话结束。一次会话中可以包含多次请求和响应
会话跟踪一种维护浏览器状态的方法服务器需要识别多次请求是否来自同以浏览器以便在同一次会话的多次请求间共享数据。
会话跟踪方案 客户端会话跟踪技术Cookie 服务端会话跟踪技术Session 令牌技术
package com.w.controller;import com.w.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;/*** Cookie、HttpSession演示*/
Slf4j
RestController
public class SessionController {//设置CookieGetMapping(/c1)public Result cookie1(HttpServletResponse response){response.addCookie(new Cookie(login_username,itheima)); //设置Cookie/响应Cookiereturn Result.success();}//获取CookieGetMapping(/c2)public Result cookie2(HttpServletRequest request){Cookie[] cookies request.getCookies();for (Cookie cookie : cookies) {if(cookie.getName().equals(login_username)){System.out.println(login_username: cookie.getValue()); //输出name为login_username的cookie}}return Result.success();}GetMapping(/s1)public Result session1(HttpSession session){log.info(HttpSession-s1: {}, session.hashCode());session.setAttribute(loginUser, tom); //往session中存储数据return Result.success();}GetMapping(/s2)public Result session2(HttpServletRequest request){HttpSession session request.getSession();log.info(HttpSession-s2: {}, session.hashCode());Object loginUser session.getAttribute(loginUser); //从session中获取数据log.info(loginUser: {}, loginUser);return Result.success(loginUser);}
}
登录校验 JWT令牌
定义了一种简洁、自包含的格式用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在这些信息是可靠的。 !--JWT令牌--dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.1/version/dependencypackage com.w;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;import javax.swing.plaf.PanelUI;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;SpringBootTest
class TliasWebManagementApplicationTests {//生成JWTTestpublic void textGenJwt() {MapString, Object claims new HashMap();claims.put(id,1);claims.put(name,tom);String jwt Jwts.builder().signWith(SignatureAlgorithm.HS256,swmdys) //签名算法.setClaims(claims) //定义令牌的有效期.setExpiration(new Date(System.currentTimeMillis() 3600*1000)) //设置有效期为1h.compact();System.out.println(jwt);}//解析JWTTestpublic void testParseJwt(){Claims claims Jwts.parser().setSigningKey(swmdys).parseClaimsJws(eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoidG9tIiwiaWQiOjEsImV4cCI6MTcwMTE4NjU5OH0.U78XufCd3VcWsPR72kUUx0RamKfDGZAahJ8oF3V2_YM).getBody();System.out.println(claims);}}
JWT令牌工具类
package com.w.utils;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;public class JwtUtils {private static String signKey swmdys;private static Long expire 43200000L;/*** 生成JWT令牌* param claims JWT第二部分负载 payload 中存储的内容* return*/public static String generateJwt(MapString, Object claims){String jwt Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, signKey).setExpiration(new Date(System.currentTimeMillis() expire)).compact();return jwt;}/*** 解析JWT令牌* param jwt JWT令牌* return JWT第二部分负载 payload 中存储的内容*/public static Claims parseJWT(String jwt){Claims claims Jwts.parser().setSigningKey(signKey).parseClaimsJws(jwt).getBody();return claims;}
}
过滤器Filter
过滤器可以把对资源的请求拦截下来从而实现一些特殊的功能 如登录校验、统一编码处理、敏感字符处理等。
添加ServletComponentScan //开启了对servlet组件的支持
package com.itheima;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;ServletComponentScan //开启了对servlet组件的支持
SpringBootApplication
public class TliasWebManagementApplication {public static void main(String[] args) {SpringApplication.run(TliasWebManagementApplication.class, args);}}过滤器链
一个web应用中可以配置多个过滤器这多个过滤器就形成了一个过滤链
配置的过滤器优先级按过滤器类名首字母自然排序
登录校验Filter package com.w.filter;import com.alibaba.fastjson.JSONObject;
import com.w.pojo.Result;
import com.w.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;Slf4j
WebFilter(urlPatterns /*)
public class LoginCheckFilter implements Filter {Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//HttpServletRequest是ServletRequest的子类HttpServletRequest req (HttpServletRequest) request;HttpServletResponse resp (HttpServletResponse) response;//1.获取请求url。String url req.getRequestURL().toString();log.info(请求的url: {},url);//2.判断请求url中是否包含login如果包含说明是登录操作放行。if(url.contains(login)){log.info(登录操作, 放行...);chain.doFilter(request,response);return;//让代码不再往下执行}//3.获取请求头中的令牌token。String jwt req.getHeader(token);//4.判断令牌是否存在如果不存在返回错误结果未登录。if(!StringUtils.hasLength(jwt)){log.info(请求头token为空,返回未登录的信息);Result error Result.error(NOT_LOGIN);//手动转换 对象--json -------- 阿里巴巴fastJSONString notLogin JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}//5.解析token如果解析失败返回错误结果未登录。try {JwtUtils.parseJWT(jwt);} catch (Exception e) {//jwt解析失败e.printStackTrace();log.info(解析令牌失败, 返回未登录错误信息);Result error Result.error(NOT_LOGIN);//手动转换 对象--json -------- 阿里巴巴fastJSONString notLogin JSONObject.toJSONString(error);resp.getWriter().write(notLogin);return;}//6.放行。log.info(令牌合法, 放行);chain.doFilter(request, response);}
}
拦截器Interceptor
Spring框架提供的一种动态拦截方法调用的机制类似于过滤器。
作用拦截请求在指定的方法调用前后根据业务需要执行预先设定的代码。
定义拦截器实现HandlerInterceptor接口 异常处理 全局异常处理器
package com.w.exception;import com.w.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 全局异常处理器*/
RestControllerAdvice
public class GlobalExceptionHandler {ExceptionHandler(Exception.class)//捕获所有异常public Result ex(Exception ex){ex.printStackTrace();return Result.error(对不起,操作失败,请联系管理员);}}
Spring事务管理
添加Transactional
作用将当前的方法交给spring进行事务管理方法执行前开启事务成功执行完毕提交事务出现异常回滚事务。
#spring事务管理日志
logging:level:org.springframework.jdbc.support.JdbcTransactionManager: debug事务属性回滚
默认情况下只有出现RuntimeException的、才会回滚异常。
rollbackFor属性用于控制出现何种异常类型回滚事务。
Transactional(rollbackFor Exception.class) //spring事务管理(所有异常都会回滚)
事务传播行为
当一个事务被另一个事务方法调用时这个事务方法和另一个事务变为了一个事务。
当我们不希望事务之间相互影响可以操作一个新的 propagation Propagation.REQUIRES_NEW
案例
解散部门时无论成功还是失败都要记录操作日志
Service
public class DeptLogServiceImpl implements DeptLogService {Autowiredprivate DeptLogMapper deptLogMapper;Transactional(propagation Propagation.REQUIRES_NEW)Overridepublic void insert(DeptLog deptLog) {deptLogMapper.insert(deptLog);}
}TransactionalOverridepublic void delete(Integer id) throws Exception {try {deptMapper.deleteById(id); //根据ID删除部门数据//int i 1/0;//if(true){throw new Exception(出错啦...);}empMapper.deleteByDeptId(id); //根据部门ID删除该部门下的员工} finally {DeptLog deptLog new DeptLog();deptLog.setCreateTime(LocalDateTime.now());deptLog.setDescription(执行了解散部门的操作,此次解散的是id号部门);deptLogService.insert(deptLog);}}AOP基础
AOP面向特定方法编程。
作用代码无侵入、减少重复代码、提高开发效率、维护方便
场景记录操作日志、权限控制、事务管理等 !--AOP--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency案例
部分功能运行较慢定位耗时较长的业务方法此时需要统计每一个业务的执行耗时
Slf4j
Component //当前类交给IOC容器管理
Aspect //AOP类
public class TimeAspect {Around(execution(* com.itheima.service.impl.DeptServiceImpl.*(..))) //切入点表达式//Around(com.itheima.aop.MyAspect1.pt())public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {//1. 记录开始时间long begin System.currentTimeMillis();//2. 调用原始方法运行Object result joinPoint.proceed();//3. 记录结束时间, 计算方法执行耗时long end System.currentTimeMillis();log.info(joinPoint.getSignature()方法执行耗时: {}ms, end-begin);return result;}}Web后端总结