当前位置: 首页 > news >正文

JavaWeb开发全流程笔记

JavaWeb

  • 前端Web开发
    • javaScript
      • 1.JS引入
      • 2.JS基础语法
      • 3.JS函数
      • 4.JS对象
    • BOM
    • DOM文档对象模型
    • JS事件监听
    • Vue
      • Vue常用指令
      • Vue的生命周期
    • Ajax
      • Axios
    • 前端工程化
      • 环境准备
      • NodeJS安装和Vue-cli安装
      • vue项目
        • Vue组件库Element
          • 组件的使用
      • Vue路由
      • Nginx打包部署
  • 后端Web开发
    • Maven
    • SpringBoot
    • HTTP协议
      • 请求数据格式
      • 响应数据格式
      • 协议解析
    • Web服务器
    • 请求响应
      • 请求参数的接收
      • 响应
    • 分层解耦
      • IOC&DI入门
      • IOC详解
      • DI详解
    • MySQL
      • SQL
      • 数据库设计
    • 多表设计
      • 1对多
      • 1对1
      • 多对多
    • 多表查询
      • 连接查询
        • 内连接
        • 外连接
          • 左外连接
          • 右外连接
      • 子查询
      • 事务
      • 索引
    • MyBatis
      • JDBC
      • 数据库连接池
      • lombok工具包
      • 基础操作
        • 配置mybatis日志
        • 预编译SQL
        • 新增主键返回
      • 数据封装
      • XML映射文件
      • 动态查询
        • 批量操作
    • 登录认证
      • 会话技术
    • 登录校验
      • JWT令牌
      • 过滤器Filter
        • 过滤器链
        • 登录校验Filter
      • 拦截器Interceptor
    • 异常处理
      • 全局异常处理器
    • Spring事务管理
      • 事务属性回滚
      • 事务传播行为
        • 案例
    • AOP基础
      • 案例
    • Web后端总结


在这里插入图片描述

前端Web开发

HTML:负责网页的结构(页面元素和内容)。
在这里插入图片描述
在这里插入图片描述
CSS:负责网页的表现(页面元素的外观、位置等页面样式,如:颜色、大小等)。
在这里插入图片描述

javaScript(Js)脚本语言。用来控制网页行为的,它能使网页交互。(交互效果)

javaScript

1.JS引入

<!-- 内部脚本 -->
<script>alert('Hello JS')
</script><!-- 外部脚本 -->
<script src="js/demo.js"></script>

2.JS基础语法

在这里插入图片描述

JS输出语句

<script>
//方式一: 弹出警告框
window.alert("hello js");//方式二: 写入html页面中
document.write("hello js");//方式三: 控制台输出,在console可以看到
console.log("hello js");
</script>

JS变量

var
var声明的变量可以接受任何数据类型的值,变量可以多次赋值,后面值把前面覆盖
var声明的变量的作用于是全局的

<script>//var定义变量var a = 10;a = "张三";alert(a);var a = 20;alert(a);
</script>

let
局部变量,不能重新定义

    <script>{let x = 1;x = 2;alert(x);}</script>

const
常量,不能重新定义,不能多次赋值

3.JS函数

<script>//定义函数function add(a,b){return a + b;}//函数调用var result = add(10,20);alert(result);
</script>

4.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);
</script>

String

<script>//定义字符串var str = "Hello";
</script>

自定义对象

<script>//自定义对象var user = {name:"Tom",age:20,gender:"male",eat: function(){alert("用膳");}};//获取对象中的属性console.log(user.name);//对象中方法的调用user.eat();
</script>

JSON

作为数据的载体,在网络中传输。

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);
</script>

BOM

浏览器对象模型,运行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(){i++console.log("定时器执行了"+i+"次")})//定时器 - srtTimeout --延迟指定时间执行一次setTimeout(function(){alert("JS")},3000);
</script>

location:地址栏对象

<script>//location:地址栏对象alert(location.href)location.href = "https://www.baidu.com/index.htm"
</script>

DOM文档对象模型

将 HTML 文档的各个组成部分封装为对象

获取DOM中的元素对象(Element对象 ,也就是标签)
操作Element对象的属性(标签的属性)

<body><img id="h1" src="img/off.gif">  <br><br><div class="cls">教育</div>   <br><div class="cls">程序员</div>  <br><input type="checkbox" name="hobby"> 电影<input type="checkbox" name="hobby"> 旅游<input type="checkbox" name="hobby"> 游戏
</body><script>//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 = "英才教育";</script>

JS事件监听

事件:发生在HTML元素上的 “事情”

事件绑定

    <script>function on(){alert("按钮1被点击了...")}document.getElementById('btn2').onclick = function(){alert("按钮2被点击了...");}</script>

常见事件
在这里插入图片描述

Vue

前端js框架

Vue快速入门

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue-快速入门</title><script src="js/vue.js"></script>
</head>
<body><div id="app"><input type="text" v-model="message">{{message}}</div></body>
<script>//定义Vue对象new Vue({el: "#app", //vue接管区域data:{message: "Hello Vue"}})
</script>
</html>

Vue常用指令

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项目的工具

  1. 依赖管理
  2. 统一项目结构
  3. 项目构建

SpringBoot

HTTP协议

超文本传输协议,规定了浏览器和服务器之间数据传输的规则

特点:
基于TCP协议:面向连接,安全
基于请求-响应模型:一次请求对应一次响应
HTTP是无状态协议,对于事物处理没有记忆能力。每次请求-响应都是独立的

优点:速度快
缺点:多次请求间不能共享数据

请求数据格式

在这里插入图片描述

在这里插入图片描述

响应数据格式

在这里插入图片描述

协议解析

Web服务器

一个软件程序,对HTTP协议的操作进行封装,让Web开发更加快捷。

主要功能:提供网上信息的浏览服务

请求响应

在这里插入图片描述

在这里插入图片描述

请求参数的接收

简单参数

实体参数

数组集合

json
在这里插入图片描述

路径参数

响应

在这里插入图片描述

分层解耦

三层架构:
复用性强、便与维护、利于扩展
在这里插入图片描述

在这里插入图片描述

内聚:软件中各个功能模块内部的功能关系
耦合:衡量软件中各个层/模块之间的依赖、关联的程度
软件设计原则:高内聚低耦合

控制反转(IOC):对象的创建控制权由程序自身转移到外部(容器)
依赖注入(DI):容器为应用程序提供运行时,所依赖的资源,称之为依赖注入
Bean对象:IOC容器中创建、管理的对象

IOC&DI入门

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-impl=org.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-case=true

模糊查询
name like ‘%${name}%’

推荐这样写:
name like concat(‘%’,#{name},‘%’)

XML映射文件

一些简单的增删改查功能推荐使用Mybatis注解。
如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。

在这里插入图片描述

官方文档地址:
https://mybatis.net.cn/getting-started.html

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">

动态查询

随着用户的输入或外部条件的变化而变化的SQL语句

    <sql id="commonSelect">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom emp</sql><!-- 动态更新员工--><update id="update2">update emp<set><if test="username != null">username = #{username},</if><if test="name != null">name = #{name},</if><if test="gender != null">gender = #{gender},</if><if test="image != null">image = #{image},</if><if test="job != null">job = #{job},</if><if test="entrydate != null">entrydate = #{entrydate},</if><if test="deptId != null">dept_id = #{deptId},</if><if test="updateTime != null">update_time = #{updateTime}</if></set>where id = #{id}</update><!-- 查询员工 --><!--resultType: 单条记录封装的类型--><select id="list" resultType="com.itheima.pojo.Emp"><include refid="commonSelect"/><where><if test="name != null">name like concat('%', #{name}, '%')</if><if test="gender != null">and gender = #{gender}</if><if test="begin != null and end != null">and entrydate between #{begin} and #{end}</if></where>order by update_time desc</select>
    //动态条件查询public List<Emp> 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 id="deleteByIds">delete from emp where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete>
    //批量删除员工public void deleteByIds(List<Integer> 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 {//设置Cookie@GetMapping("/c1")public Result cookie1(HttpServletResponse response){response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookiereturn Result.success();}//获取Cookie@GetMapping("/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令牌--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
package 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 {//生成JWT@Testpublic void textGenJwt() {Map<String, 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);}//解析JWT@Testpublic 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(Map<String, 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);}
}
    @Transactional@Overridepublic 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--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-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后端总结

在这里插入图片描述

在这里插入图片描述

相关文章:

JavaWeb开发全流程笔记

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…...

LLM;超越记忆《第 2 部分 》

一、说明 在这篇博客中&#xff0c;我深入研究了将大型语言模型&#xff08;LLM&#xff09;提升到基本记忆之上的数学框架。我们探索了动态上下文学习、连续空间插值及其生成能力&#xff0c;揭示了 LLM 如何理解、适应和创新超越传统机器学习模型。 LLM代表了人工智能的重大飞…...

Python中的加法测试题实现

随机生成5道10以内的加法测试题&#xff0c;用户在10秒内使用键盘输入答案。完成全部5道答题之后&#xff0c;计算机生成答题记录报告&#xff0c;并对答题情况进行分析&#xff0c;显示“答对了”&#xff0c;或“答错了”、并显示正确答案。如果未能按时完成&#xff0c;则显…...

使用gcloud SDK 管理和部署 Cloud run service

查看cloud run 上的service 列表&#xff1a; gcloud run services list > gcloud run services listSERVICE REGION URL LAST DEPLOYED BY LAST DEPL…...

JS逆向-mytoken之code参数

前言 本文是该专栏的第60篇,后面会持续分享python爬虫干货知识,记得关注。 本文以mytoken为例,通过js逆向获取其code参数的生成规律。具体的“逆向”思路逻辑,笔者将会详细介绍每个步骤,并且将在正文结合“完整代码”进行详细说明。 接下来,跟着笔者直接往下看正文详细…...

第九节HarmonyOS 常用基础组件4-Button

一、Button Button组件主要用来响应点击操作&#xff0c;可以包含子组件。 示例代码&#xff1a; Entry Component struct Index {build() {Row() {Column() {Button(确定, { type: ButtonType.Capsule, stateEffect: true }).width(90%).height(40).fontSize(16).fontWeigh…...

常用数据预处理方法 python

常用数据预处理方法 数据清洗缺失值处理示例删除缺失值插值法填充缺失值 异常值处理示例删除异常值替换异常值 数据类型转换示例数据类型转换在数据清洗过程中非常常见 重复值处理示例处理重复值是数据清洗的重要步骤 数据转换示例 数据集成示例数据集成是将多个数据源合并为一…...

【无标题】AttributeError: module ‘gradio‘ has no attribute ‘outputs‘

问题描述 AttributeError: module gradio has no attribute outputs 不知道作者用的是哪个gradio版本&#xff0c;最新的版本报错AttributeError: module gradio has no attribute outputs &#xff0c; 换一个老一点的版本会报错AttributeError: module gradio has no attribu…...

无人机助力电力设备螺母缺销智能检测识别,python基于YOLOv7开发构建电力设备螺母缺销小目标检测识别系统

传统作业场景下电力设备的运维和维护都是人工来完成的&#xff0c;随着现代技术科技手段的不断发展&#xff0c;基于无人机航拍飞行的自动智能化电力设备问题检测成为了一种可行的手段&#xff0c;本文的核心内容就是基于YOLOv7来开发构建电力设备螺母缺销检测识别系统&#xf…...

动态页面技术的发展与应用

jsp 静态页面&#xff1a;web诞生后的html文档&#xff0c;不论多少次访问都是同一份html文档或者是其他的什么文档&#xff0c;所以说是”静态“的。 虽然js能让页面产生互动&#xff0c;但是不论什么人访问&#xff0c;看到的都是放在服务器的那一份写死的文件/文档activexa…...

1-算法基础-编程基础

1.基本数据类型 char ch A; char s[] "hello";2.const定义常量 const int N 1e5 9;//const定义常量&#xff0c;后续不可被修改 int a[N];3.万能头文件 C11等可用 #include<bits/stdc.h> using namespace std;4.typedef typedef long long kk; kk a[20…...

HarmonyOS应用开发——程序框架UIAbility、启动模式与路由跳转

前言 UIAbility简单来说就是一种包含用户界面的应用组件&#xff0c;用于和用户进行交互。每一个UIAbility实例&#xff0c;对应于一个最近任务列表中的任务。 一个应用可以有一个UIAbility&#xff0c;也可以有多个UIAbility。一个UIAbility可以对应于多个页面&#xff0c;建议…...

node.js-连接SQLserver数据库

1.在自己的项目JS文件夹中建文件&#xff1a;config.js、mssql.js和server.js以及api文件夹下的user.js 2.在config.js中封装数据库信息 let app {user: sa, //这里写你的数据库的用户名password: ,//这里写数据库的密码server: localhost,database: medicineSystem, // 数据…...

目标检测YOLO系列从入门到精通技术详解100篇-【图像处理】图像预处理方法

目录 前言 知识储备 Opencv图像操作 几个高频面试题目 为什么需要图像算法? 算法原理...

Android drawable layer-list右上角红点,xml布局实现,Kotlin

Android drawable layer-list右上角红点&#xff0c;xml布局实现&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <layer-list xmlns:android"http://schemas.android.com/apk/res/android"><itemandroid:id"id…...

网络虚拟化场景下网络包的发送过程

网络虚拟化有和存储虚拟化类似的地方&#xff0c;例如&#xff0c;它们都是基于 virtio 的&#xff0c;因而在看网络虚拟化的过程中&#xff0c;会看到和存储虚拟化很像的数据结构和原理。但是&#xff0c;网络虚拟化也有自己的特殊性。例如&#xff0c;存储虚拟化是将宿主机上…...

《数据结构与测绘程序设计》试题详细解析(仅供参考)

一. 选择题&#xff08;每空2分&#xff0c;本题共30分&#xff09; &#xff08;1&#xff09;在一个单链表中&#xff0c;已知q所指结点是p所指结点的前驱结点&#xff0c;若在q和p之间插入结点s&#xff0c;则执行( B )。 A. s->nextp->next; p->nexts; B. q…...

Raft 算法

Raft 算法 1 背景 当今的数据中心和应用程序在高度动态的环境中运行&#xff0c;为了应对高度动态的环境&#xff0c;它们通过额外的服务器进行横向扩展&#xff0c;并且根据需求进行扩展和收缩。同时&#xff0c;服务器和网络故障也很常见。 因此&#xff0c;系统必须在正常…...

Redis队列stream,Redis多线程详解

Redis 目前最新版本为 Redis-6.2.6 &#xff0c;会以 CentOS7 下 Redis-6.2.4 版本进行讲解。 下载地址&#xff1a; https://redis.io/download 安装运行 Redis 很简单&#xff0c;在 Linux 下执行上面的 4 条命令即可 &#xff0c;同时前面的 课程已经有完整的视…...

ThinkPHP的方法接收json数据问题

第一次接触到前后端分离开发&#xff0c;需要在后端接收前端ajax提交的json数据&#xff0c;开发基于ThinkPHP3.2.3框架。于是一开始习惯性的直接用I()方法接收到前端发送的json数据&#xff0c;然后用json_decode()解析发现结果为空&#xff01;但是打印出还未解析的值却打印得…...

简单理解算法

简单理解算法 前言算法衡量一个好的算法具备的标准算法的应用场景 数据结构数据结构的组成方式 前言 hello&#xff0c;宝宝们~来分享我从一本书中理解的算法。《漫画算法》感觉对我这种算法小白比较友好。看完感觉对算法有了新的理解&#xff0c;计算机学习这么多年&#xff…...

C/C++ 内存管理(2)

文章目录 new 和 delet 概念new 和 delet 的使用new与 delete 底层原理malloc/free和new/delete的区别new / opera new / 构造函数 之间的关系定位new表达式(placement-new)内存泄漏内存泄漏分类如何对待内存泄漏 new 和 delet 概念 new和delete是用于动态内存管理的运算符&am…...

Net6.0或Net7.0项目升级到Net8.0 并 消除.Net8中SqlSugar的警告

本文基于NetCore3.1或Net6.0项目升级到Net7.0&#xff0c;参考连接&#xff1a;NetCore3.1或Net6.0项目升级到Net7.0-CSDN博客 所有项目按照此步骤操作一遍&#xff0c;完成后再将所有引用的包&#xff08;即 *.dll&#xff09;更新升级到最新版&#xff08;注意&#xff1a;有…...

力扣题:字符串的反转-11.22

力扣题-11.22 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;541. 反转字符串 II 解题思想&#xff1a;进行遍历翻转即可 class Solution(object):def reverseStr(self, s, k):""":type s: str:type k: int:rtype: str"&quo…...

Effective C++(二):对象的初始化

文章目录 一、类的初始化二、全局静态对象的初始化 一、类的初始化 对于类中的成员变量的初始化&#xff0c;一般有两种方法&#xff0c;一种是在类中定义的时候直接赋予初值&#xff1a; class CTextBlock { private:std::size_t textLength{ 0 };bool lenisValid{ false }:…...

云原生高级--shell自动化脚本备份

shell自动化脚本实战---备份 数据库备份&#xff1a; 结合计划任务 MySQL、 Oracle 网站备份&#xff1a; tar&#xff0c;异地保存--ftp、rsync 一、数据库备份 1.利用自带工具mysqldump 实现数据库分库备份 分库备份&#xff1a; 1> 如何获取备份的…...

Spring Boot实现热部署

Spring Boot提供了一个名为spring-boot-devtools的开发工具&#xff0c;它可以实现热部署功能。通过使用spring-boot-devtools&#xff0c;可以在修改了resources目录下的内容后&#xff0c;自动重新加载应用程序&#xff0c;而无需手动重启。 以下是使用spring-boot-devtools…...

MVCC-

文章目录 1. 什么是MVCC2. 快照读和当前读3. 复习4. MVCC实现原理之ReadView5. 总结 文章目录 1. 什么是MVCC2. 快照读和当前读3. 复习4. MVCC实现原理之ReadView5. 总结 1. 什么是MVCC 口述&#xff1a;MVCC其实他是解决这种读-写的情况的&#xff0c;当然读-写也可以用 锁来…...

键盘打字盲打练习系列之刻意练习——1

一.欢迎来到我的酒馆 盲打&#xff0c;刻意练习! 目录 一.欢迎来到我的酒馆二.选择一款工具三.刻意练习第一步&#xff1a;基准键位练习第二步&#xff1a;字母键位练习第三步&#xff1a;数字符号键位练习 四.矫正坐姿 二.选择一款工具 工欲善其事必先利其器。在开始之前&…...

某公司前端笔试题(12.30)

1、对象数组去重&#xff1a; 数组去重&#xff1a; const a[{a:1,b:2},{a:2},{a:2},{a:1,c:3},{b:2,a:1}] 结果&#xff1a;[{a:1,b:2},{a:2},{a:1,c:3}] // 判断两个对象的属性值是否一致 const a [{ a: 1, b: 2 }, { a: 2 }, { a: 2 }, { a: 1, c: 3 }, { b: 2, a: 1 }] co…...