ssmpro
笔记2

2104-ssmpro 学习的内容目录
> spirngboot  vue  node.js  京淘  nginx  redis  mycat # ssmpro2104本阶段学到的*动态为属性赋值springboot的开箱即用mybatis-plusStringUtils spring提供的字符串工具类spirngmvc流程@CrossOriginmd5加密,登录uuid秘钥,免登陆token session/cookie登录成功后跳转, 前端路由机制层级菜单, 层级列表mybatis分页查询mybatisPlus日期数据自动填充事务回滚全局异常处理商品分类列表查询, 一级二级三级, 使用map集合新增两个表, 主键自动回显文件上传nginx  反向代理,负载均衡 策略nginx图片回显(后端返回给用户url,回显时图片是url,使用nginx反向代理url到本地)hosts 本地域名关联tomcat集群 nginx配置 proxy_passlinux部署 tomcat集群,nginx(web)# ssmpro2104本阶段学到的# lombok # 框架
> springmvc : 接收,返回数据   交互
> spirng : 整合第三方框架   整合
> mybatis : 整合jdbc   持久化
> spirngboot : 简化spring框架操作   简化springboottomcatspirngspirngmvc controllerservicemybatis dao> 注解 :dao  接口--@Mapper   实现类--@Repositoryservice   实现类--@Servicecontroller  @RestController
# tomcat
> springboot中自带tomcat  spring中没有# springboot 应用># 1. maven 命令clean    清空target文件目录compile  编译maven工程install  项目打包># 2. 坐标<groupId>com.jt</groupId>                          组Id 项目主目录<artifactId>springboot_demo1</artifactId>          项目名称 名称唯一<version>0.0.1-SNAPSHOT</version>                  依赖版本> 2.0 坐标作用唯一标识项目路径    项目打包路径   ># 3. pom.xml 文件添加jar包,依赖> 3.1 parent标签依赖于Springboot项目(框架) , 由spring官网维护 , 其中几乎定义了所有的框架与SpringBoot兼容的版本信息集中定义版本号> 3.2 dependencies 添加jar包, 使项目依赖jar包, 那项目中就有什么功能> 3.3 build起到的作用使项目打包依赖 插件># 4. SpringBoot配置文件> 4.1 .propertieskey-value 结构   语法: key=value 例如: server.port=8614   都是字符串类型程序I/O读取该配置文件, 默认编码是ISO-8859-1 , 中文需要指定字符集> 4.2 .ymlkey-value 结构  语法: key:(空格)value层级结构 父子级语法缩进默认编码utf-8编辑springboot使其与第三方框架整合># 5. 动态为属性赋值 类里   @Value> 5.1 使用yml配置文件 application.yml定义: userinfo: name: 吕晶1    定义在配置文件中 当springboot启动时会自动加载配置文件 使用: @value(${userinfo.name})private String name;表达式: ${name} springel表达式 spel表达式 加载配置文件, 数据加载到map集合中, spel表达式可以通过key获取map中的value并赋值> 5.2 properties 配置文件  user.properties定义: userinfo2.name2=吕晶2   使用: 使程序读到此文件 @PropertySource 根据路径,加载配置文件,交给spirng容器管理@PropertySource(value="classpath:/user.properties",encoding="utf-8") 描述类使用: @value(${userinfo.name})private String name;># 6. SpringBoot 核心机制: 开箱即用   只需导入特定的jar包文件, 则可以直接使用其功能Spring不行SpringBoot进行了框架的简化, 扩展了, 简化了配置信息的书写,加入jar包就能使用># 7. 热部署, lombok> lombok链式加载  @Accessors(chain = true) 重写了set方法使set方法有返回值,使得set方法可以链式加载User user = new User(); user.setName("l"); user.setAge(23); user.setSex(1);  user.setName("lvj").setAge(23).setSex(1); 如何实现? 前一个返回该对象后面的就能继续调用public User setName(String name){this.name = name;return this;}> idea中lombok使用需要安装插件, 在linux中运行需要安装插件吗不要lombok在编译期有效, 编译后的.class文件已经生成对应的方法, 没有了lombok的注解项目发布时 .class文件打包为 .jar文件 , 不需要lombok环境># 8. 测试代码联调:在测试中 使用创建controller对象,调用方法   但controller中依赖注入了service层代码不用SpringBootTest 会报错 原因: 创建使用的类的对象,没有依赖注入不能使用对象中的依赖注入 @SpringBootTest-降低代码联调  测试启动的是springboot工程,对于项目中使用的所有依赖注入创建的对象, 都可以使用Springboot依赖注入, 把所有对象放在-容器-中, SpringBootTest会从bean中获取需要的对象## 程序是如何加载的> 启动类使用SpringApplication.run() 加载的是本类上的注解@SpringBootApplication># 9. 容器加载规则  SpringBoot加载器顺序1) 启动类main方法启动程序, 2) 加载类的注解@SpringBootApplication3) 获取当前主类所在包(com.cy)4) 包扫描机制, 扫描的是类上的注解, 特定的注解所在类交给spring的容器管理ioc-di5) 容器中的结构 Map<K,V> key-类名 value-对象   Map<UserDao,userDao>6) 使用容器中的对象: @Autowired依赖注入 容器中有注入成功7) 容器启动成功, 使用注入的对象即可调用类中的资源--启动类注解@SpringBootApplication, 包扫描, 容器Map<K,V>, @Autowired--># 10. SpringBoot 整合mybatis> 类: 主启动类> 1) yml 配置文件spring.datasourceurl : # useUnicode=true&characterEncoding=utf8  存数据取数据 utf8 <--> GBK编码 互转# serverTimezone=GMT%2B8  GMT+8  %2B代表+# autoReconnect=true  断线是否重连# allowMultiQueries=true  是否运行批量操作password: lvjing   # 密码使用0开头 要使用""包括  "01234"mybatis.type-aliases-package: com.cy.pojo    # 设置别名包> 2) 依赖注入 代理对象注入的是对象, 面向接口开发: 接口不能创建对象,Spring为接口创建代理对象,就是克隆一个接口创建对象代理: 根据原有对象的模型, 在运行期动态创建了一个一模一样功能的实例对象jdk默认代理  class com.sun.proxy.$Proxy67> 3) sql写法xml : UserMapper.xml  注解 :@Insert("")@Delete("") @Select("select id,name,age,sex from demo_user where id = #{id}")@Update("")># 11. SpringBoot 整合  mybatis-plus  单表操作通过配置,单表的crud  mybatis增强工具> 我要用的方法     便利userDao.insert(user);   user中设置添加的值.deleteById(242);   .deleteBatchIds(list);  list中为删除的所有 id .delete(queryWrapper); where条件.update(user,updateWrapper);  user为修改的内容, updateWrapper为条件.updateById(user);  user中设置id 和 要修改的值.selectById(247);.selectList(queryWrapper); queryWrapper.eq("name","lvjing"); >1, 实现没有xml文件1) 依赖  mybatis-plus-boot-starter2) 编辑pojo实现对象 和  数据表 关系对象 映射到 表@TableName(value="demo_user") 属性 映射到 字段@TableId(type = IdType.AUTO)  主键@TableField(value = "name")   普通属性 与 字段(非主键)名一致, 注解可省略3) dao接口  继承公共的接口,获取常用crud操作BaseMapper<User>4) yml 配置mybatis-plus: 5) 使用对象的方式操作数据库测试  直接使用api操作数据crud@TableName("user")public class User extends BasePojo implements Serializable{}@Mapperpublic interface UserDao extends BaseMapper<User> {}>2, 类pom.xml  mybatis-plus-boot-starterpojo     User.java  --@TableName(value="demo_user")  @TableId(type=IdType.AUTO) @TableField(value="name")dao      UserDao.java --extends BaseMapper<User>application.yml   mybatis-plus: test     Api  --userDao.insert(user);>3, APIinsertselect       参数   ById     1List     new QueryWrapper(user)  条件构造器 封装where条件 objs     null   只获取主键id的值deleteById     100  updateById     User   修改除id以外 所有不为空null的数据> 修改 id=241 的 name为lvyingyinguser.setId(241).setName("lvyingying");userDao.updateById(user);update> 修改 name=lv 的 name,age,sexuser.setName("lvyingying").setAge(99).setSex("男");UpdateWrapper updateWrapper = new UpdateWrapper();updateWrapper.eq("name","lv");userDao.update(user,updateWrapper);>4, 条件构造器 where   QueryWrapper<User>QueryWrapper<User> queryWrapper = new QueryWrapper();1) 使用User对象User user = new User();user.setName("lvjing");QueryWrapper<User> queryWrapper = new QueryWrapper(user);    System.out.println(userDao.selectList(queryWrapper));2) name=lvjing 直接传参数, 不使用User对象    eq是=  QueryWrapper<User> queryWrapper = new QueryWrapper();    queryWrapper.eq("name","lvjing").or().eq("sex","女");System.out.println(userDao.selectList(queryWrapper));3) age>18 且 sex=女QueryWrapper<User> queryWrapper = new QueryWrapper();queryWrapper.gt("age",18).eq("sex","女");System.out.println(userDao.selectList(queryWrapper));4) 常用逻辑运算符 = eq, > gt, < lt, >= ge, <= le, != ne 5) 关键字 like   1. like "%lv%"--queryWrapper.like("name","lv")  2. like '%lv'--queryWrapper.likeLeft("name","lv");in     1. queryWrapper.in("id",236,237,238);           2. Integer[] ids = {236,237,238}; queryWrapper.in("id",ids);order by       where sex='男' order by age desc   queryWrapper.eq("sex","男").orderByDesc("age");group by> 动态sql.eq(boolean condition, R column, Object val)select * from demo_user where age > 20 and sex = '男'queryWrapper.gt(ageBoo,"age",age).eq(sexBl,"sex",sex);          Integer age = 18;String sex = "女";boolean ageBoo = age != null;boolean sexBoo = sex != null && sex.length() > 0;boolean sexBl = StringUtils.hasLength(sex);# 可变参数类型 放在参数里的最后   test(String name, Integer age, Integer... grade)# StringUtils  org.springframework.util.StringUtils; spirng提供的,在spring框架中都可以用boolean sexBl = StringUtils.hasLength(sex);  判断sex是否为 空 或 null># 12.springmvc> 项目结构pom.yml   type-aliases-package: com.lvjing.sys.pojopojo 实体一般实现序列化接口 implements Serializable dao  使用mybatis-plus 继承接口 extends BaseMapper<User> 启动类中@MapperScan("com.lvjing.sys.dao") 为dao接口创建代理对象># 13.controler 注解@PathVariable        @RequestBody  @ResponseBody1. @PathVariable  请求url为RestFul格式 http://localhost:8614/user/findById/{id}@GetMapping("findById/{id}")public User find(@PahtVariable Integer id){}@DeleteMapping("/user/{id}")public void deleteUser(@PathVariable Integer id){}2. @RequestBody    前端post/put请求传递后端 json串格式   注解将JSON串格式转换为User对象@PostMapping("insert")public int insert(@RequestBody User user){}@PutMapping("updateUser")public void updateUser(@RequestBody User user){}3.RestController返回值都是json串4.CrossOrigin跨域 url/ajaxurl># 14.vue># 16.servlet机制Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。概念: java实现前后端数据交互的一种机制核心对象: Request对象(存储提交的数据)   浏览器 -> java后端Response对象(服务器端返回数据信息)  java后端 -> 浏览器> 后端路由 / 后端返回页面  页面在class中写@Controller配置: mvc-># 17.springmvc 执行流程/调用流程图
> 组件1. 前端控制器 DispatcherServlet 实现请求的流转2. 处理器映射器 实现了请求路径与方法之间的映射.3. 处理器适配器 处理器的管理器 内部有N个处理器. 针对不同的用户请求 调用不同的处理器完成任务4. 视图解析器 直线页面路径的拼接
> 父子容器父子容器概念:1.Spring容器(内存中的一大块空间)由于IOC/DI的机制,可以作为第三方的管理者 所以作为父级.2.SpringMVC容器,其中只负责Controller层的相关的对象的管理.说明: 当SpringMVC容器启动时,提前将SpringMVC中的所有请求路径方法方法完成映射.
> 流程1. 用户发起请求时,第一步经过前端控制器,2. 但是前端控制器 只负责请求的转发和响应.不做任何业务处理.将请求转发给处理器映射器.3. 处理器映射器接收到前端控制器的请求之后,查询自己维护的服务列表信息.如果服务列表中没有这个URL的key. 该程序不能处理用户的请求,则返回特定数据,前端控制器接收之后响应用户404.如果服务列表中有该URL key 则说明请求可以正常执行. 将该方法的对象返回给前端控制器.4. 前端控制器将返回的方法进行接收,但是由于前端控制器只负责转发和响应,不能直接执行该方法.所以交给处理器适配器执行.5. 处理器适配器根据方法的类型(xml配置文件/注解/其他方法),处理器适配器在自己的处理器库中挑选一个最为合适的处理器去执行该方法. 当处理器执行该方法时标识业务开始. 将最终的处理的结果通过ModelAndView对象进行包裹,返回给前端控制器.ModelAndView: Model: 代表服务器返回的业务数据 View: 服务器端返回的页面的名称6. 视图解析器 将View中的数据进行解析 拼接一个完整的页面路径 前缀/hello后缀7. 视图渲染: 将数据与页面进行绑定. 这样用户就可以在页面中看到具体的数据.8. 由于现在流行前后端分离. 所以SpringMVC省略了视图解析和视图渲染.只有前5步. 核心注解: @ResponseBody 省略6-7步># 15.jt项目前端, main.js - App.vue - router/index.js - component/Login.vue> 1. 项目结构1) 启动类   @MapperScan("com.jt.sys.pojo")2) pojo     @Accessors(chain=true)  implements Serializable3) controller   @CrossOrigin> 2. 用户登录操作 校验> 加密方式MD5加密/MD5Hash/sha1String md5DigestAsHex = DigestUtils.md5DigestAsHex(password.getBytes());> uuid32位16进制数  16^32   (2^4)^32   2^128   3.4*10^38时间戳进行的hash, 毫秒String uuid = UUID.randomUUID().toString().replace("_","");> 3. 后端返回 token 前端需要保存, 如何存储?. Session-会话控制/会话机制 : 存储用户信息(所需属性和配置), 用户会话存在期间, 信息一致存在当用户在app中的网页之间跳转时, 存储在Session对象中的变量不会丢失, 在整个用户会话中保存下来  * 短时间内(会话期间)有效. Cookie- : 网站识别用户身份, 将session中的信息保存到计算机本地, 暂时或永久保存加密的数据* 一段时间内有效 例如:七天免密登录.. 例如:session 安全  银行, 财务, 员工  cookie        腾讯会员.. 使用: 前端: session//获取用户token信息(后端返回的)let token = result.datawindow.sessionStorage.setItem("token",token)cookie.. 查看:浏览器: F12 Application/Session Storage...解决 登录之后(页面跳转)的用户信息展示在首页中, > 3. 登录成功首页跳转    前端vue elementui   this.$router.push("/home")路由中添加 /home 组件> 4. 左侧菜单 权限一级菜单 二级菜单先把一级菜单查出来,根据一级菜单的id(二级菜单的parentid)查找对应的二级菜单, 把查找出来的二级菜单放到对应的一级菜单中,
> 5. 分页查询  展示用户信息* 1. mybatispageResult  query/pageNum/pageSize/total/rows使用mapper映射文件 sql进行分页查询  limit (pageNum-1)pageSize,pageSize   limit 起始位置,条数* 2. mybatisplus配置类@Configuration标识是一个配置类 代替xml文件分页// xml 标签管理,将对象给Spring管理  <bean>// 配置类 方法管理,将返回值给Spring管理 @Bean/*** MybatisPlus分页*      设定一个拦截器, 将指定的sql 动态拼接*/// 最新版@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));return interceptor;}> 6. mybatis-plus 数据自动填充   日期 添加https://mp.baomidou.com/guide/auto-fill-metainfo.html1. pojo 要自动填充数据的@TableField(fill = FieldFill.INSERT)private Date created;  //表示入库时需要赋值2. 配置类实现 MetaObjectHandler接口 重写方法  入库操作  更新时操作方法: //setFieldValByName(arg1,arg2,arg3)//arg1: 自动填充的字段名称   arg2: 自动填充的值   arg3: metaObject 固定写法> 写方法时要考虑的问题# 不知道的
> 7. 控制业务层事务    deleteById(id)   删除的 回滚    事务
. 例如 业务层  数据删除成功,但方法失败userDao.deleteById(id);  成功int i = 1/0;  失败整个方法失败, 但数据删除成功
. 原子性,一个方法中的业务,要么同时成功,要么同时失败
. 注解 @Transactional  Spring中事务控制核心: AOP中的@Around通知,实现对事物控制@Around: 环绕通知, 业务执行前.开启事务控制-执行目标方法-业务执行后.成功`提交/失败`回滚用法: 写在要使用事务的方法上事务策略: 1.运行时异常,回滚  算数,空指针,数组下标越界  5-7个2. 检查异常(编译异常),不回滚  Exception, 程序已经提示的异常,程序员自己处理,spring不管理属性: rollbackFor 遇到什么类型异常 回滚 noRollbackFor  遇到什么类型异常 不会滚 使用默认策略
. @Transactional  修改.删除.更新> 8. 根据AOP定义全局异常处理 机制
. 不能保证所有操作都正常, 使用功能try-catch异常, 但代码冗余
. 解决代码冗余, spring4的全局异常处理
. springmvc的全局异常处理类 advice/GlobalExceptionHandler
. 注解: @RestControllerAdvice Around通知, 放回json串, 捕获的是controller层异常, 其他层会抛给controller@RestController/@Controller 描述的类中发生异常且没有处理, spring会查找注解@RestControllerAdvice描述的类, 进行异常处理
. 类: @RestControllerException 描述 class GlobalExceptionHandler
. 方法: @ExceptionHandler 描述 JsonResult doHandlerRuntimeException(Exception e){}e.printStackTrace();// 打印return new JsonResult(201,"",e);> 9. 商品分类列表查询  -- for                内存数据结构                   运行速度
1. 商品分类表, 1级菜单 > 2级菜单 > 3级菜单
2. 优化 查询速度分页查询一次,使用map集合https://blog.csdn.net/qq_40055619/article/details/118611141> 10.123端口占用: netstat -ano | findstr "8091"   | 管道 先执行前面再执行后面> 11. 商品新增  商品详情信息入库,两个表添加数据
. 新增的数据有两部分 1.商品item 2.商品详情   > 前端传入数据  > 后端使用封装了item和itemdesc的ItemVO接收
. 新增, 两个新增操作.. 主键自动回显功能问题; item新增的数据id 要和itemDesc新增的id一样,  解决:  0不行  直接使用查询, 把刚刚新增的查一次得到id  -这种方式存在问题, 如果有相同的数据 id就不一样了1. mybatis的主键自动回显功能  新增之后把新增的数据的id回显<insert id="xxxx" useGeneratedKeys="true" keyProperty="id" ketColumn="id"></insert>2. mybatis-plus 实现了主键自增功能  新增之后id就有值了itemDao.insert(item); 之前 item的id为空, 之后 item的id为新增数据的iditem.getId() 这里就有值了> 12.富文本 vue-quill-editor> 13. 文件上传前端: http://localhost:8614/file/upload后端: 存储文件: 文件放在本地目录, 1. virtualPath 存本地实际路径,不包含磁盘信息2. urlPath url访问, 其他人通过此url访问, 看到文件3. fileName  控制文件上传后的文件名
缓冲流一次搬运多大的字节效率最高?       1024
业务参数:  MUltipartFile 私密性
文件上传:前端 el-upload 上传文件后端 把文件保存在指定目录中  file.transferTo(new File(path))数据库 一条记录保存对应的文件目录, 当要查看/使用时通过路径调用指定目录的文件
> 上传1. 验证文件的类型, 图片 文件后缀, 正则  ^.+\\.(jpg|png|gif)$2. 进一步验证是否是图片, 使用图片特有的特征, 具有 宽高, 3. 把文件放在一个目录下, 检索费时间, 分目录存储  方法: 1.按时间 2.hash(hash存在问题-某些可能会被经常访问,某些不会被访问到)4. 文件名 不重名, uuid5. 实现文件上传  拼接全路径,上传/*** 实现上传:*      1. 验证上传文件是图片--文件后缀   ..校验字符串--正则表达式  木马.exe.jpg  图片特有--分辨率*      2. 防止恶意攻击, 验证图片是否有分辨率*      3. 文件分目录存储  1)时间-一天一个  2)8位16进制hash xx/xx/xx/xx*          hash: 造成数据分配不均, 可能会有某些经常被访问, 而有些不被访问*      4. 文件名 重名  uuid*      5. 实现文件上传*          拼接全路径, 完成上传** 实现动态赋值:*      编辑配置文件: image.properties*          localDirPath     preUrlPath*      导入 image.properties配置文件*.          @PropertySource(value="classpath:/image.properties",encoding="utf-8")*.          @Value("${file.localDirPath}")** 实现删除:*      deleteFile   参数: ImageVO-VirtualPath** 实现预览:** 上传两份相同的, 本地中会有两份, ????*/// 上传路径   优化: 使用配置文件动态属性赋值@Value("${file.localDirPath}")private String localDirPath;// 虚拟路径@Value("${file.preUrlPath}")private String preUrlPath;@Overridepublic ImageVO upload(MultipartFile file) {// 1. 校验图片类型是否正确, 正则   a.jpg// 获取文件名String fileName = file.getOriginalFilename();fileName = fileName.toLowerCase(); // 全部转换为小写// 正则String regex ="^.+\\.(jpg|png|gif)$";// bug  正则中  .JPG   java区分大小写if (!fileName.matches(regex)){return null;}// 2. 校验文件是否为恶意程序,  判断文件是否有分辨率 宽 高// 将文件转换为图片对象try {BufferedImage bufferedImage = ImageIO.read(file.getInputStream());  // file转换为图片对象// 获取宽高int height = bufferedImage.getHeight();int width = bufferedImage.getWidth();if (height==0 || width==0){return null;}// 3.文件分目录存储// 按时间分配String dateDirPath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());// 文件根目录String localDir = localDirPath+dateDirPath;// 目录不存在,创建File dirFile = new File(localDir);if (!dirFile.exists()){dirFile.mkdirs();}// 4.文件名, 重名  uuid 2^128// 文件名String uuid = UUID.randomUUID().toString().replace("-","");// 后缀int index = fileName.lastIndexOf(".");String fileType = fileName.substring(index);// 文件名+后缀   089aa0fe087a4ebaa896ee7ce1314a08.pngString realFileName = uuid + fileType;// 5.文件上传// 拼接全路径  目录/文件名   localDir realFileNameString localFilePath = localDir + realFileName;// 文件上传file.transferTo(new File(localFilePath));/*** 目录 :*      本地磁盘: D:\AIT\Java\eSSMPro\ideassmprotwo\h-jt\src\main\resources\static\images*      时间分配: \2021\07\13\*      文件名: 089aa0fe087a4ebaa896ee7ce1314a08.png*      文件本地路径: D:\AIT\Java\eSSMPro\ideassmprotwo\h-jt\src\main\resources\static\images\2021\07\13\089aa0fe087a4ebaa896ee7ce1314a08.png**      虚拟前缀: http://image.jt.com*      没有盘符: \2021\07\13\089aa0fe087a4ebaa896ee7ce1314a08.png*      虚拟路径: http://image.jt.com/2021/07/13/089aa0fe087a4ebaa896ee7ce1314a08.png*/// 返回imageVOString imageVOVirtualPath = dateDirPath+realFileName; // 没有磁盘路径String imageVOUrlPath = preUrlPath+imageVOVirtualPath; // 虚拟路径String imageVOFileName = realFileName; // 文件名return new ImageVO(imageVOVirtualPath,imageVOUrlPath,imageVOFileName);} catch (IOException e) {e.printStackTrace();return null; // 终止程序}}# nginx
> 14.nginx
1. 反向代理机制   服务端代理自己理解: 用户发起请求, 为了保护目标服务器中资源的安全性, 在用户与目标服务器之间使用代理服务器, 用户发起请求访问代理服务器代理服务器转发请求给目标服务器, 目标服务器把数据给代理服务器, 代理服务器再把数据给用户保证里目标服务器的数据安全, 也保证了用户的安全, (用户不知道目标服务器真正的访问请求, 目标服务器也不知道用户的信息)不知道原始服务器, 不知道真正的资源, 安全反向代理服务器  用户与目标服务器之间,    用户通过访问反向代理服务器就能获取目标服务器资源, 通常用在web加速器(降低了网络和服务器的负载,提高了访问效率)特点:1. 反向代理服务器 介于用户和目标服务器之间2. 用户以为反向代理服务器就是目标服务器 3. 用户不知道真正的请求地址4. 用户与目标服务器 互相不知道5. 反向代理服务器中存储的是 用户的访问地址与目标服务器真正的访问地址的映射步骤:1. 用户向代理服务器发送请求,(以为代理服务器就是真实目标服务器)2. 代理服务器接收请求时,根据自己的映射文件,重新发起新的请求 访问真实的目标服务器.3. 根据映射路径,查找真实的服务器资源.4. 获取资源返回给代理服务器.5. 代理服务器将资源交换给用户.2. 正向代理机制   客户端代理自己的理解:客户端才能正向代理, 用户访问原始服务器受限(某种原因), 正向代理在用户和原始服务器中间, 用户可以访问正向代理服务器 正向代理可以访问原始服务器用户(指定目标)通过访问正向代理, 正向代理访问原始服务器, 获取数据清楚知道要访问的资源是啥, 由于某些机制受限  用户访问vpn特点:1. 正向代理介于用户和目标服务器之间2. 用户很清楚要访问原始服务器的资源是什么3. 一般正向代理实现的是网络之间的通信正向代理和反向代理服务器:用户---(正向代理)--->某某服务器------>反向代理服务器------>{业务服务器1,业务服务器2,...}客户端代理: 保护了用户信息服务端代理: 保护了服务器信息3. nginx概述:高性能http和反向代理web服务器, C语言开发, Nginx是一个主流的 反向代理服务器 / 负载均衡服务器特点:1. 占用内存少, 启动一个服务运行内存不到2M,2. 并发能力强, 5万/秒 实测:2-3万/秒科普: 单台tomcat服务器并发能力 220/秒 JVM调优 增大JVM运行内存空间配合服务器监控.根据当前硬件设备进行优化. 经过JVM调优之后的tomcat服务器 可以达到 1000/秒4. nginx安装下载解压, .exe文件 运行, 运行之后两个进程进程: 主进程(主要提供反向代理服务) 守护进程(防止主进程意外关闭)5. nginx命令启动: start nginx          只负责启动, 没有报错信息重启: nginx -s reload      重启服务, 含有报错信息, 没有报错信息nginx启动成功停止: nginx -s stop6. nginx配置文件 nginx.confhttp{# 每一个反向代理服务都是一个server     http://localhost:8704/server {# 监听端口listen       8704;# 拦截用户访问路径server_name  localhost;# 反向代理具体配置项  location (具体配置) / (拦截所有请求)# root 代表目录html# index 默认访问页面location / {root   html;index  index.html index.htm;}error_page   500 502 503 504  /50x.html;location = /50x.html {root   html;}}}> 14.图片回显/浏览器预览
1. 用户使用的url地址: http://image.jt.com/2021/07/13/089aa0fe087a4ebaa896ee7ce1314a08.png    本地路径:         D:\AIT\Java\eSSMPro\ideassmprotwo\h-jt\src\main\resources\static\images\2021\07\13\089aa0fe087a4ebaa896ee7ce1314a08.png没有映射url和本地路径
2. 解决:用户访问http://image.jt.com  映射到D:\AIT\Java\eSSMPro\ideassmprotwo\h-jt\src\main\resources\static\images
3. 反向代理配置 nginx.conf  图片的映射serverserver{listen        80;server_name   image.jt.com;location / {root   D:\AIT\Java\eSSMPro\ideassmprotwo\h-jt\src\main\resources\static\images;}}
4. 图片反向代理原理image.jt.com 的域名 发到了公网, 不能访问解决: HOSTS文件 -主要在本机实现 域名与ip的映射 image.jt.com 与 172.18.6.35 HOSTS文件位置: C:/windows/system32/drivers/etc/hostsHOSTS文件:127.0.0.1 localhost127.0.0.1 image.jt.com重启nginx权限问题:属性-安全-编辑当前用户的权限文件属性-高级-更改权限-添加当前用户的权限反向代理实现原理自己理解:文件的上传(本地)目录--自己设置filePath用户访问的url--自己设置virtualPath. 通过filePath把上传的文件保存到本地, 返回给用户virtalPath路径进行访问nginx实现 反向代理  image.jt.com 和  D:\AIT\Java. 通过配置文件nginx.config 中的 server(是一个反向代理服务) . nginx只要配置好 启动, 当使用到反向代理是会自动映射, 不用在自己的服务中配置域名问题:image.jt.com的域名 会在公网汇总请求, 要在自己电脑上使用配置hosts文件 127.0.0.1 image.jt.com> 15.nginx域名代理      前后端服务发布  打包
1.项目 编译后端: 8614   为前端提供数据支持前端: 8080  借助tomcat服务器  生产环境中前端是静态资源(需要打包发布)
2.域名访问前端: 访问前端http://web.jt.com:8080/后端: 访问后端http://manage.jt.com:8614/前端访问后端: http://manage.jt.com:8614/
3.前端打包->静态资源文件脚手架 build文件目录 dist
4.前端访问使用 http://web.jt.com 访问打包后dist中index.html文件反向代理  nginx.confserver{listen          80;server_name     web.jt.com;location / {root        dist;index       index.html;}}hosts    域名 web.jt.com# 访问前端域名127.0.0.1       web.jt.com
5.后端访问http://manage.jt.com  反向代理 localhost:8614nginxserver{listen          80;server_name     manage.jt.com;location / {proxy_pass       http://localhost:8614;}}hosts# 访问后端域名127.0.0.1       manage.jt.com
6.后端打包mavencleaninstall8614/86157.整合前端放在nginx中, 启动nginx, 访问前端域名就能访问前端后端打包,nginx.conf 反向代理http{# 图片代理  图片回显server{listen          80;server_name   image.jt.com;location / {root   D:/AIT/Java/eSSMPro/ideassmprotwo/h-jt/src/main/resources/static/images;}}# 前端代理  web.jt.com 访问 京淘首页server{listen          80;server_name     web.jt.com;location / {root        dist;index       index.html;}}# 后端代理  前端请求 manage.jt.com  访问后端localhost:8614server{listen          80;server_name     manage.jt.com;location / {proxy_pass       http://localhost:8614;}}}
.hosts    域名   # 京淘项目# 访问图片域名127.0.0.1       image.jt.com# 访问前端域名127.0.0.1       web.jt.com# 访问后端域名127.0.0.1       manage.jt.com> 16.tomcat服务搭建   部署tomcat服务器集群   nginx使用
原因: nginx 2万/秒, 但是8614服务器只能1000/秒,
解决: 搭建后端服务器集群, 分担压力, 端口号
1.集群:物理结构, 多态服务器(物理服务器), 一台物理设备可以部署多个tomcat服务,
2.nginx的负载均衡: 一个 nginx 多个服务器 , 要请求哪1个服务器, 就是负载均衡upstream tomcats{}# 负载均衡  轮循upstream tomcats {server localhost:8614;server localhost:8615;}server {listen 80;server_name  manage.jt.com;location / {proxy_pass  http://tomcats;}}
3.权重机制性能高的服务器, 让其经常访问weight=6upstream tomcats{server localhost:8614 weight=1;server localhost:8615 weight=9;}
4.iphash用户与服务器绑定   -用户指定服务器进行访问upstream tomcats {ip_hash;server 127.0.0.1:8615 weight=1;server 127.0.0.1:8614 weight=9;}iphash算法hash(ip:port)%2  余数5.nginx高可用
高可用HA
服务器宕机, 实现自动化故障迁移, 无需人为干预6.nginx策略一个服务器访问不同, 自动访问下一台轮循权重iphash插件7.nginx属性down     该属性标识的服务器, nginx永远不会访问此服务器backup   设置备用机, 正常不提供服务, 如果其他设备宕机, 则访问该备用机max_fails=1        访问失败的最大次数fail_timeout=60s   失败的超时时间, 在超时时间范围内, 不会再次访问故障机> 17.linux
1.命令ip addrclearpwd   当前目录位置tab键   自动补齐cd    切换目录cd, cd ~, cd /, cd ., cd .., cd /usr/local/srcls   展示文件目录,    ll 总用量mkdir   创建目录,  mkdir abc ,  mkdir -p a/aa/aaa  多层目录, mkdir -m 777 c 权限为777的目录,  rmdir 删除非空,rm  删除文件, rm a.txt, rm -f a.txt, rm -r c, rm -rf c,    rm删除文件, -f没有提示, -r递归 删除目录(非空也行),       rm -rf * 删除本目录所有vi/vim   编辑文件,  i 插入,   esc :wq 保存退出,   esc u 撤销,  esc :set nu 展示行号,    esc :q!   感叹号强制退出,     :quit 退出cp 复制 , cp a.txt a.txt.cp 复制文件,  cp -r a b复制目录,  mv 移动 , mv b.txt b b.txt移动到b,  mv a.txt b.txt 改名,tar包  -cvf -zcvf打包 -xvf解压,tar –cvf n.tar ./* 压缩当前目录下的所有文件和目录,文件名为n.tartar –xvf n.tar 解压压缩包中的文件到当前目录(如果长时间未解压成功 Ctrl+C推出)tar –cvzf m.tar.gz ./* 压缩文件tar -zxvf m.tar.gz      解压m.tar文件到当前目录2.环境搭建目录   /usr/local/src/jdk   解压 tar -xvf n.tar配置环境变量:  vim /etc/profile# 设定jdk环境export JAVA_HOME=/usr/local/src/jt/jdk/jdk1.8export PATH=$JAVA_HOME/bin:$PATHexport CLASSPATH=.:$JAVA_HOME/lib使其作用:      source /etc/profilelinux配置文件      vim   /etc/profile/   3.数据库yum install mariadb-serveryum 像是linux的应用商城yum  clean   all                 清空已安装文件   如果下载失败之后执行的.1.   启动命令        systemctl  start  mariadb2.   重启命令        systemctl  restart  mariadb3.   关闭命令        systemctl  stop  mariadb4.   设定开机自起    systemctl  enable mariadb 5.   关闭开机自起    systemctl  disable mariadb 数据库初始化:  mysql_secure_installation登录: mysql -uroot -proot导入数据库: source /x/x/x/x/xxxx.sqllinux的数据库权限mysql库select host,user,password from user;update user set host = "%" where host = "localhost";% 代表任意ip刷新数据库权限flush privileges;4.liunx防火墙firewall-cmd --state  防火墙状态systemctl enable/disable firewalld.service   防火墙开机自启/关闭systemctl start/stop firewalld.service       手动开启/关闭防火墙手动开放防火墙端口firewall-cmd --list-ports  检查防火墙开放的端口firewall-cmd --query-port 80/tcp  80端口是否开放firewall-cmd --zone=public --add-port=80/tcp --permanent     开启防火墙端口firewall-cmd --zone=public --remove-port=9090/tcp --permanent   移除端口–zone #作用域–add-port=80/tcp #添加端口,格式为:端口/通讯协议–remove-port=80/tcp #移除端口,格式为:端口/通讯协议–permanent #永久生效,没有此参数重启后失效firewall-cmd --reload 重启防火墙5.部署tomcat服务修改原始服务1.文件上传地址  改成linux本地目录打包后端服务8614.jar复制到linux父目录 java -jar 8614.jar & 运行> 18.tomcat集群   后端服务器集群
1.启动8614/8615java -jar 8614.jar & java -jar 8615.jar &jps linux检索java服务项所有进程号kill pid号(进程号)  常规   linux手动关闭某个服务的进程项,杀进程     kill -15 pid号 强制   kill -9 pid号 无法逆转2.使tomcat服务器 后台运行   关闭终端后服务不关闭nohup java -jar 8614.jar linux后台运行日志单独保存nohup java -jar 8615.jar => logs/8615.log3.关闭进程ps -ef 查看所有进程项ps -ef | grep java    | 管道,以第一个的结果作为第二个的条件    ps -ef 的结果  作为grep java 的参数4.查看日志cat 输出所有more/less 分页  空格..下一屏  q..退出 tail -10 8614.log   只展现后面几行tail -f 8614.log   动态查看日志5.脚本启动服务vim start.sh   创建脚本文件内容:#!/bin/shnohup java -jar /usr/local/src/jt/jtservice/8614.jar => /usr/local/src/jt/jtservice/logs/8614.log &nohup java -jar /usr/local/src/jt/jtservice/8615.jar => /usr/local/src/jt/jtservice/logs/8615.log &执行:sh start.sh./ 当前目录  .当前 /目录> 19.linux部署 nginx
1.nginx安装包nginx-1.21.1.tar.gztar -xvf nginx-1.21.1.tar.gz
2.文件说明/usr/local/src/jt/nginx/nginx-source    源文件目录, 安装配置nginx
3.nginx安装配置nginx:configure 脚本文件  执行   ./configurenginx path : /usr/local/nginx编译:make  nginx配置文件所在目录安装:make install检查:whereis nginx启动:/usr/local/nginx  目录下./nginx  运行./nginx -s reload./nginx -s stop查看:ps -ef | grep nginx
4.nginx部署webimage      web.jt.com     manage.jt.com把前端dist目录放到nginx目录下 /usr/local/nginxconf目录 nginx.conf# 前后端集群配置 server{}修改hosts文件, 用户在windowsxia访问C:\Windows\System32\drivers\etc\hosts# 京淘项目   linux# 访问图片域名192.168.126.129       image.jt.com# 访问前端域名192.168.126.129        web.jt.com# 访问后端域名192.168.126.129       manage.jt.com# 项目部署在linux中
>后端jdk mysql 服务打包运行   8614.jar 8615.jar  start.sh(脚本运行)
>前端nginx:下载nginx的linux安装包  nginx-1.21.1.tar.gz复制到linux解压执行nginx脚本./configure, 编译make, 安装make install, 启动/usr/lcoal/nginx/sbin  ./nginxweb服务:把打包后的web目录复制到nginx安装后的目录中 /usr/local/nginxnginx配置web:修改conf/nginx.conf  域名映射server{listen ;server_name ;location / {root ;index ;} }
>用户访问用户在windows下访问, 域名关联修改hosts文件192.168.126.129  web.jt.com# 二阶段整理
> 框架梳理1.环境idea, maven2.框架spirngboot:  pom.xml application.yml/application.properties(@PropertySource("classpath:/user.properties") @Value("${file.path}"))lombok:@Data @Access(chain=true)mybatis:  @MapperScan("com.jt.sys.dao") 为持久层接口产生代理对象代理对象:jdk动态代理: 必须有接口cglib动态代理: 有无接口都行, 代理对象时被代理者的子类mybatisPlus:以对象方式操作数据库3.前端ajax:局部刷新,异步请求(客户端,ajax引擎,后端服务器)跨域:同源策略: 请求协议://域名:端口号   应该都相同ajax请求网址 和 浏览器网址违反同源策略  浏览器网址:     http://localhost:8080/userList.htmlajax请求网址:   http://localhost:8614/abc/a协议不同 域名不同(映射的也不行) 端口不同解决: 跨域资源共享cros机制, 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。浏览器都支持改功能后端服务器通过响应头信息添加允许访问的域名地址,后端UserController @CrossOrigin注解# ssmpro2104本阶段学到的*动态为属性赋值springboot的开箱即用mybatis-plusStringUtils spring提供的字符串工具类spirngmvc流程@CrossOriginmd5加密,登录uuid秘钥,免登陆token session/cookie登录成功后跳转, 前端路由机制层级菜单, 层级列表mybatis分页查询mybatisPlus日期数据自动填充事务回滚全局异常处理商品分类列表查询, 一级二级三级, 使用map集合新增两个表, 主键自动回显文件上传nginx  反向代理,负载均衡 策略nginx图片回显(后端返回给用户url,回显时图片是url,使用nginx反向代理url到本地)hosts 本地域名关联tomcat集群 nginx配置 proxy_passlinux部署 tomcat集群,nginx(web)
# ssmpro2104本阶段学到的

笔记1

## 单体架构
### spirng boot, spring, mybatis####   2021-03-03  ----------------------------
Chrome 的插件
IDEA  后端   无限试用版
VSCode 用户界面GC  垃圾回收IDEA每一个Project都有自己的配置    maven 本地仓库  jdksettings.xml本地库,远程库,jdk,<localRepository></mirror><profile>####   2021-03-04  ----------------------------
>>>>    回顾dosc.google.com石墨文档语雀
Chrome 插件
pdf chrome://flags
utf8 插件set character encoding
格式呈现JSON数据  jsonview>>>>  -设置---------
settings.xml本地库,远程库,jdk,<localRepository></mirror><profile>
IDEA设置maven     builder toolsutf8           file Encoding包导入        jdk1.8      builder/compiler/java compilderkeymap       代码提示        代码补全
IDEA项目empty project 相当于工作空间module 小写  package 小写cn.tedurebuild清缓存   file/ invalidate caches/restart
项目配置project structure     jdk
>>>>    main 中的 args 参数 作用:  接收运行时的传入的数据,edit configurations    编辑配置  program arguments 接收依赖 chrome
https://mvnrepository.com/项目结构
project structure ctrl+alt+shift+s>>>>   Git全局配置  ***** ** *检查git配置git config --list配置git用户   全局用户配置git config --global user.name "赵庆"git config --global user.email "2792837349@qq.com"idea 中 git操作配置git                   version control中Git 找到此电脑已安装的git检测        plugins安装gitee插件登录                        version control中gitee登录创建本地库                vcs中create git repository 查看本地库             settings中的version controlexclude文件配置        .git/info  add                      项目右键 git add 然后commit  directorycommit                  提交到本地仓库history 怎么切换     查看历史版本share到远程仓库            分享到远程仓库   只执行一次push                         每次本地修改后 add  commit push远程库 修改 创建文件 update                          更新本地仓库clone                             克隆远程仓库克隆的项目配置 jdk maven utf8 maven项目添加到maven区                pom.xml 文件上右键选择 add as maven projectjava项目                                      src 转换为 sources   root 格式exclude文件配置  .git/info  作用: 对上传的资源过滤,哪些提交,上传HELP.mdtarget/out/### IntelliJ IDEA ###.idea*.iws*.iml*.ipr.gitignore### maven ###mvnw*.cmd.mvn/####   2021-03-05  ----------------------------
# 系统公告业务描述系统原型设计 页面      数据库分层设计 http    tcp    >>>>  数据库命令行set names utf8;  客户端编码status    数据库状态source 路径   导入数据库 执行.sql文件表  sys_noticesidea连接数据库 name jt@localhosturl:     jdbc:mysql://localhost:3306/jt?serverTimezone=GMT%2B8&characterEncoding=utf8mb4数据库操作>>>>   spring boot  框架 脚手架>>>>   创建spring initializr  spring初始化修改运行名>>>>   spring boot @SpringBootApplication springboot运行入口1.启动类  做了什么类:  交给spring管理 的类   不交给spring管理的类1).将磁盘中的类    读到内存 (位置, 技术--线程调用io读)2).类的信息的提取   构建对象  存储对象3).读取对象配置信息  对系统进行初始化配置扫描包,磁盘读取,线程io读取,读到内存,创建字节码对象.class,第一个加载的类?2.如何知道哪些类被加载到内存?jvm参数的配置  -XX:+TraceClassLoading         作用: 对类的加载过程进行呈现edit configurations ( run/debug configurations配置 )  environment环境 (vm  args directory variables  )  3.类文件读到内存后注解 描述数据的元数据 (类 参数)(数据对象)读取到容器中bean   多个bean存在map<String,BeanDefinition>中BeanFactory反射实例   创建对象存到map<String,Object>可重复用的对象1) 基于线程调用 i/o 从磁盘读取类,将其加载到内存,此时会基于类创建字节码对象(其类型为 Class 类型)
2) 基于 Class 对象(字节码对象)读取类的配置信息(例如类上有什么注解-例如@Component,属性上有什么注解,....)
3) 基于类的配置进行相应的配置存储 ( 交 给 spring 管理的类的配置 )-Map<String,BeanDefinition>
4)  基 于 类 的 配 置 借 助 BeanFactory 创 建 类 的 实 例 ( 对 象 ), 多 个 对 象 存 储 到
Map<String,Object>>>>>>>>>池化思想:享元模式提升系统性能    高效  低耗
>>>>   springboot   使用    hikariCP    连接数据库
>>  池01-javaseIntegerTests.java
200不在integer -128到127内>>  为什么使用连接池  频繁的数据库连接关闭影响性能     TCP协议 3次握手 4次挥手??????????????>>  数据源规范javax.sql.DataSource 接口           不同团队创建不同连接池对象  耦合接口(规范)  方便切换不同商家   >>  数据库连接池原理 构成??????????????>>  hikariCP依赖 mysql data-jdbc04-notice-ssm  DataSourceTest    数据源http://github.com/alibaba/nacos
liaochuntao
jdbc>>>>  双重校验if(a==null){synchronized(this){if(a==null){}}}
保证安全提高并发
>>>>  时区GMT%2B8Asia/Shanghai>>>> 注意:************
错误看 cause by>?????????????????<utf8mb4idea调试 几个按钮运行错误not bean 如何解决?     依赖注入问题  导包 jdbc依赖添加
>?????????????????<####   2021-03-08  ----------------------------
## 回顾
>>>>  jdbc 访问数据库DataSource 对象  连接池熟悉jdbc  步骤     封装在具体的对象中获取连接创建Statement发生sql处理结果释放资源??    为什么使用 PreparedStatement 作用Statement不能识别?>>>>  jdbcTests.java   testSelectNotices01()为什么使用list封装map?map是一行数据,用list存储多行元数据(标题 描述数据的数据) 数据返回值在业务对象中,测试类中没有,       业务方法在main中
dao接口 dao实现类(包含jdbc) 代码用活sql values封装  输入@Repoditory标明这是一个数据访问对象**-------jdbc-------**
> 1. 依赖:pom.xmlmysqljdbc
> 2. 连接数据库配置:application.propertiesspring.datasource.url=jdbc:mysql://localhost:3306/jt?characterEncoding=utf8&serverTimezone=GMT%2B8.username = root  .password = root
> 3. 测试连接:DataSourceTests.java测试dataSource的连接对象: HikariDataSource测试类使用的注解:@SpringBootTest   修饰类     这是springboot的测试类@Autowried         修饰属性        自动装配,在ioc容器中查找并返回属性,@Test                  修饰方法        测试类
> 4. JdbcTests.java获取数据源对象,连接数据库,对数据库进行操作jdbc步骤:建立连接conn = dataSource.getConnection()创建Statement/PreparedStatementstmt = conn.createStatement() /  conn.preparedStatement(sql)发送sqlstmt.execute(sql);处理结果释放资源stmt.close();conn.close();testInsertNotices01()Statement创建 不需要动态传入SQL值testInsertNotices02()Preparedment创建  使用?动态输入  pstmt.setObject(index,x)testSelectNotices01()查询需要获取查询结果    对结果集处理 每一行放在map中,每个map放在list中 返回给用户   map.put()存储到map中testSelectNotice02()使用元数据获取字段名,,,不需要写很多个map.put()  只要循环元数据就行
> 5. 最终实现写在main里面使用接口实现类NoticeJdbcDao.javaNoticeJdbcDaoImpl.javaNoticeJdbcDaoTests.java
> 6. 用活把insert的sql语句和添加的值values作为参数传入程序测试时定义SQL语句 调用方法传参值values 使用object数组传入方法     实现类中foreach循环object数组获得值
*?*
自己创建的接口 使用时no bean  接口实现类的@Repository(标识这是一个数据访问对象的具体实现类)
**-------jdbc-------**####   2021-03-09  -------------------------------------------------------------
SysNotice.java pojo
SysNoticeDao.java  interface
SysNoticeMapper.xml
NoticeDaoTests.java  test>>>>  JdbcTemplate类模板 封装了jdbc编程步骤>>>>  mybatis依赖, spring 框架启动时会对 mybatis 进行自动配置。SqlSessionFactory 工厂对象的创建。
官网: mybatis.org/spring    http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/使用mybatis需要sqlsessionfactory和mapper interface>>>>  业务实现接口 @Mapper Dao data access object 数据访问对象两类对象 1.业务 2.存数据sysnotice>> 04-notice-ssmpojo 对象    创建接口     .xml配置文件      test测试*-*    pojo    SysNotice.java      pojo 对象私有属性 get set toString方法
*-* dao SysNoticeDao.java 数据持久层接口查询删除修改新增
*-* mapper/sys  SysNoticeMapper.xml 文件头 官网:https://mybatis.org/mybatis-3/getting-started.htmlselectNotices*-*   test    NoticeDaoTests.javaspringboot管理的类  有@Autowired  会在bean池中查找SysNoticeDao对象是     Proxy代理对象       a实现b a is a b的特殊   ( is  a )testSelectNotices()创建对象SysNotice,通过对象封装要写入到数据库的数据执行方法, 返回list    循环list输出**--项目--**
01-javase  VarParamTest.java   可变参数
04-notice-ssmpojo   SysNotice.java      dao SysNoticeDao.javamapper/sys SysNoticeMapper.xml test    NoticeDaoTests.java####   2021-03-10  -----------------------------------------------
读取数据库内容,   写入数据库is a     继承实现
has a   有一个   对象和它的成员的从属关系>>>>   @Qualifier("sysNoticeDao")*表明了哪个实现类才是我们所需要的*@Autowired默认按照类型匹配注入bean,如果有多个实现类,搭配@Qualifier(“实现类名称”)表明注入的是哪一个实现类的bean
同时有多个同名的实现类 使用@Service修饰  有 @Service("a")  @Service("b")  @Service("c")@Autowried修饰的需要用到的属性使用@Qualifier("a") 标明使用a的实现类日志 SLF4J日志级别  error > info > debug(调试信息)  >  trace(跟踪程序时)>>>>  spring web过滤器 filterchain
处理流程:1) DNSurl设计 Rest风格
**-- 项目 --**
SysNoticeDaoImpl.java 自己写的实现类
SysNoticeServiceTest.java
LogTest.java
####   2021-03-11  ----------------------------
代理对象>>    JsonTests.java
服务端 数据返回给 客户端   返回的转换为JSON字符串     转换为指定对象JSON字符串跨平台 {"key":vlaue,"key":value}    [{},{},{},{}]>>>>  postman     测试服务get     查询post      新增put       更新delete    删除
>>>>  Spring Framework   资源整合框架
**https://spring.io/**IoC   控制反转AoPWeb>>>>  修改日期格式@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss,timezone="GMT+8")  描述属性或get方法时间差8小时 转换时按照 格林威治 时间     timezone = "GMT+8"
>>>>  使用时间查询   2021-03-12 15:27:12   不能用 springmvc不能处理          2021/03/12 15:27:12@DataTimeFormat(pattern="yyyy-MM-dd HH:mm:ss)   描述属性或get方法>>>>   CRUDcreateretyieveupdatedelete
>>>>  controller@RestController@RestMapping("Contants.NOTICE_ROOT_PATH")>>>>  异常处理规范springmvc中提供的**--项目--**
JsonTests.java
SysNoticeController.java    添加控制层  使用url访问     用postman测试400 客户端向服务端传递的参数 类型 格式 个数####   2021-03-12  ----------------------------
>>>>  拦截器请求数据处理 预处理      响应数据加工方法 preHandler
>>>>   过滤器  Filters   >>>>   分页插件          拦截器接口的底层代理实现类  通过sqlsession与数据库会话  过程中拦截  改变sql语句limit #{startIndex},#{pageSize}>>>>   封装请求对象     工具类  获取方法参数的  util         获取请求对象中的参数信息http://localhost/notice/?pageCurrent=1&pageSize=2>>>> 注解括号中直接写值,是给注解的value属性赋值**--项目--**
SpringwebConfig.java
TimeAccessInterceptor.java
MainTest.java
SysNoticeController.java中的查询拦截ThreadTests.java Lamdba简化使用接口方法
ListTest.java 迭代listServletUtil.java
PageUtil.java
StringUtil.java
工具类  在业务层上提取 同性代码####   2021-03-15  ----------------------------
# web1.初始思想
模块: controller -访问> service -访问> Dao -访问> database
请求url:Rest风格      ???????请求方式:类@RequestMapping()方法    在postman中使用相同连接 不同的请求方式  执行的是不同的方法@GetMapping(处理 Get 请求,主要应用于查询)@PostMapping(处理 post 请求,主要应用于新增操作)@PutMapping(处理 put 请求,主要应用于更新操作)@DeleteMapping(处理 delete 请求,主要应用于删除操作)请求方法参数类型    ?????????pojo 使用@RequestBody      application/json1) 直接量(8 中基本数据类型+String+Date+数组)2) Pojo 对象(必须提供 set 方法)3) Map 对象(必须使用@RequestParam 或@RequestBody 注解描述)# 拦截器# 插件  分页#### 框架      封装了servlet对象   响应对象
# 看重性能   使用底层原始   servlet       javaEE规范
# javaEE三剑客   Filters  Servlet  listener监听
# Servlet接口 java中的
# ctrl+H实现   继承体系
# servlet处理请求返回response# tomcat/jetty web容器
实现规范DispatcherServlet.java   servlet拿到请求  - request.setCharacterEncoding("utf-8")- String str = request.getParameter("pageCurrent")- Integer.parseInt(str)- service.doMethod()- response.setCharacterEncoding("utf-8")- reponse.setContentType("application/json")- PrintWriter pw = reponse.getWriter()- pw.wirte(content)- pw.flush()mvc 是一种设计思想  实现规范# 依赖  没有写版本
parent指定了 版本
scope什么时候有效annotationProdessor编译时有效# 插件  Lombok作用:  简化代码 1.安装插件    2.启动注解处理    3.依赖    4.pojo中的方法    没有get方法 不能将对象转换为Json字符串
>>>>  LombokTests.java>>>> 如何写一个Lombok编译原理>>>> 注解
@JsonFormat() 底层创建get方法
Lombokpojo中@Setter  在编译时  会在.class文件中添加set方法@Getter  在编译时  会在.class文件中添加get方法@ToString 在编译时  会在.class文件中添加toString方法@NoArgsConstructor 无参构造@AllArgsConstructor 全参构造@Date@EqualsAndHashCodelog impl中@Slf4j 会创建Logger log常量# 热部署插件
>>>>  作用: 类在更改内容后    自动重启服务加载类(main resourdes ),不是所有的类(静态资源  test类 )
>  ClassLoader   类加载器.class文件   从磁盘/网络读到内存中
>>>>  过程?????> 依赖 devtools# 泛型 <E>ArrayList<E>   第一个E是泛型方法, 第二个E是泛型类型约束1)是编译时一种类型, 运行时无效用于约束类中 属性   方法参数类型   返回值类型类型擦除?在运行时泛型会变成Object2)应用场景: 框架-共性, 工具类-, 通用方法泛型方法减少检查3)类型: 类泛型, 方法泛型class ClassA<T>{} class ClassB<K,V,B>{}类泛型: 主要约束类中 实例属性, 非静态方法参数, 非静态返回值类型static class Contentr<E>{void add(E e){}E add(){return null;}}<T>void<T> method()应用最多 静态方法 static <T>void print(T t){}这是一个泛型方法 参数类型要写T  必须泛型是T(左边)方法泛型:<泛型>返回值类型<泛型>4)泛型限定通配符?   无界? super   有限  下届限定通配符   存数据时     <? super String>  使用Object? extends  继承  上届限定通配符  获取数据时  <? extends Number> 使用Integer Long5)用在哪里在collections.java01-javase   GenericTests01.javaGenericTests02.javaListGenericTests01.java>>>>  泛型编译时特性  反射运行时特性# collections.java java中的集合工具类返回值类型左侧有泛型 就是泛型方法# 序列化接口 Serializable 存数据####   spring 资源整合框架框架底层提供的资源自己写的资源######################### 遇到问题 先保留现场 what when where
阿里/美团 日志  ?????
###  05-log-aop
## 数据库表
## 创建项目直接添加依赖
## pojo
## Dao
## SysLogMapper.xml
## Service
## Controller# 依赖mysqlspring-jdbcwebmybatispagehelper spring-bootspring-boot-devtoolslombokspring-boot testspring-boot-maven-pluginjunit### AOP拿取用户日志    异步日志存储到数据库####   2021-03-16  ----------------------------
# 项目
## 添加数据库数据
## 创建项目 添加依赖
## 配置application.properties
## mybatis层      1.pojo请求标准  2.dao接口  3.sql语句SysLogMapper.xml
## service层       1.接口   2.实现类
## controller层   1.controller      2.接收resultset的pojo(JsonResult)响应标准
### web controller, jsonresult, exception, PageUtil, StringUtil, ServletUtil,    # 条件语句
mybatis.org/mybatis-3/dynamc-sql.htmlDynamic SQL动态sql
where-if
choose-when
####  高内聚低耦合 # 项目依赖于项目# 耦合于接口class SysLogServiceImpl 业务层实现类  耦合于数据层接口 SysLogDao# AOP
如何在不修改源代码的基础上对对象功能进行拓展
1.继承: 强耦合
2.实现+耦合 组合
*--------*
A
B实现A 耦合A
扩展了C(注入A)
*--------*
>>> aop 设计思想      oop ioc mvc mvvm1.面向切面编程 是面向对象的补充和完善2.横向切面  功能的扩展/增强   @SLF4J/@Mapper> 把扩展的业务写在切面中
> 广义封装
> 基于运行时动态####   2021-03-17  ----------------------------
java基础,GC,多线程,数据库索引,jvm原理,jdk源码
美团招聘job.meituan.com/job.alibaba.com# AspectJ 框架  面向切面编程  -可以从字节码
添加依赖整合了aspectj
*注解 jdk1.5*
*耦合于接口调用实现类*
> 切面对象,为目标业务方法做功能增强
>> 1.创建注解, 应用于切入点表达式的定义RequiredLog.java给方法上加 扩展功能定义注解:@Target() 应用于哪里 方法,类,属性@Retention() 什么时期有限  编译时,运行时属性:String value() default "";  使用( @Retention(value="lvjing") )时给value赋值,可以不用写value,有默认值可以不用赋值  String operation();  @Retention(operation="lvjing")>> 2.创建切面对象, 用于日志业务增强SysLogAspect.java@Aspect     切入点定义@Component  组件1.方法定义切入点   **切入点@Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")      由RequiredLog注解描述的方法 为切入点方法2.切入点执行时执行的方法   **通知方法@Around("doLog()")  调用目标方法** 代理对象 业务层不写实现类底层框架产生代理对象  controller耦合代理对象** 切面为service层增强  具有切入点注解的方法进行增强** 使用日志 要在工厂中获取日志  @SLF4J** 切面对象的 返回值不加分页 return result; 有值return null;    无值加分页 切入点返回值有没有 都会返回控制端值-- 原因: 分页是mybatis层的 数据层  会在切入点之前执行 所以有结果** -- 基于aop代理   CGLIB代理    是实现类的子类(继承)   controller耦合service实现类-- 基于组合代理 jdk代理            实现service接口++  底层代理类调用了 use a 切面
AI
Big Data
Cloud>> 3.获取并记录详细日志       练习10遍1.获取用户行为日志 获取并赋值pojo2.封装用户行为日志 pojo封装3.打印到数据库>>>>   步骤
> 1.RequiredLog.java    特点注解定义注解  定义一个属性获取operation     作用: 在方法上使用注解@Retention()  运行时期@Target()  可以用在哪里  类 方法 属性
> 2.SysLogAspect.java切面对象 作用: 日志业务增强@Aspect   此注解描述的类是切面类型, 封装 切入点 和 通知方法切入点       在特点注解描述的地方进行扩展业务通知方法    扩展的逻辑业务@Component   ####   2021-03-18  ---------------------------->>> aop是什么  思想,>>>   注解AnnotationTests.java获取类的注解的值获取类中属性的注解的值
>>> classRelationTests.javais a     实现,继承has a  注入 private use a  使用 类.属性(方法)
>>>  无限循环StackOverflowErrorTests>>>>  通知类型@Around (优先级最高的通知,可以在目标方法执行之前,之后灵活进行业务拓展.) @Before (目标方法执行之前调用) @AfterReturning (目标方法正常结束时执行)@AfterThrowing (目标方法异常结束时执行) @After (目标方法结束时执行,正常结束和异常结束它都会执行)
> RequiredTime.java定义注解 切入点方法
> SysTimeAspect.java通知类型的执行顺序@Around@Before@After@AfterReturning@AfterThrowing顺序: @Around(优先级最高) 本类其他before  其他切面before  目标方法  当前或其他切面的后续通知方法    //栈>>>>   切面执行顺序
@Order(Ordered.HIGHEST_PRECEDENCE)
@Order(Integer.MIN_VALUE)@Order(1)@Aspect@Componentpublic class SysTimeAspect {}@RequiredTime@Order(2)@Aspect@Componentpublic class SysLogAspect {}@RequiredLog>>>>  Spring AOP切入点表达式>>>>  耗时    ??????查询时调用新增日志加了模拟耗时 时 第二个查询不能出结果查询时的线程   新增时的线程????       查询频繁的写日志  线程阻塞了&&&       异步记录日志下订单时   数据库  日志 卖家 库存  积分 .....  返回给用户结果>>>>>  异步记录日志tomcat是个进程 有多个 线程   不用来执行耗时 存日志线程重用 -> 池化思想 -> 池中线程的重用 ->    线程池(自己建,框架的池)>>>>框架的线程池  在启动类中加@EnableAsync    ----启动时,初始化线程池
> 方法上加 @Async 描述的方法为一个异步切入点方法>> 异步执行时 获得结果的时间  两个线程的执行顺序或者不在一个cpu  ThreadTests02.javastackoverflow 网站>>> 异步 返回结果
public Future<Integer> saveLog(SysLog sysLog) {return new AsyncResult<>(rows);
}>>>>>    Spring Thread Pool核心线程数  cpu核数*2+磁盘数    4*2+1
ThreadPoolExecuter  java提供的线程池java  tomcat  spring   都有线程池线程池参数:?????>>>>>    AtomicLong   递增对象    +atomicLong.getAndIncrement()####   2021-03-19  ----------------------------
#   线程
> 线程工厂 new Thread(){@override run() }.start();  Runable中的run方法
>*自增 : AtomicLongTests.java
>*线程安全: CountTests.javacas算法  cpu自带的docs.google.com# 事务deleteById让已删除的数据回滚   @Transactional 单体架构可以spring中的事务控制 是通过aop进行控制的
>*SysLogServiceImpl.java 删除不成功回滚事务
@Transactional *业务层*描述的方法 事务切入点方法(功能增强 DataSourceTransactionManager.java   所有事物都是connection在控制)   可以加在类上doBegin()    doCommit()  代理对象 通过事务对目标对象的 目标方法进行功能增强在执行时先开启事务  ?谁来调用 -TransactionAspectSupport中的通知业务 进行功能增强*每层都会有事务 底层存在*
> @Transactional属性
* 所有的读写 都用true/false
readOnly=false    --就是增删改时不能读
timeout=60       --超过时时之后业务没结束就不等了
rollbackFor=RuntimeException.class  --运行时出异常回滚
isolation=Isolation.READ_COMMITTED 没有脏读- 锁              ??????悲观锁:
- 多事务并发执行时 并发问题  ?? 脏读, 不可重复读, 幻读(统计)   -------修改事务的隔离级别脏读: 别的人读取了别人没有提交的事务 A(a1,a2,a3) B()  A执行a1没提交, B获取了a1,B的a1就是脏读   =隔离级别读别人已提交的不可重复读: A事务没结束,B把事务更新了       A读多次,每次一样,但出现了不一样就是不可重复读    =不让B更新 加锁幻读: A正在统计100, B删了10     A读到100 , 实际90    =给表加锁脏读 :: 一个事务中访问了另一个事务未提交的数据不可重复读 :: 一个事务查询同一条记录多次, 查到的结果不一样幻读 :: 一个事务查询两次得到的记录条数不一致>  SysLogServiceImpl.java类 @Transactional(readOnly = false,timeout = 60,rollbackFor = Throwable.class,isolation = Isolation.READ_COMMITTED)findLogs   @Transactional(readOnly = true) # 代理对象
> 01-javase   JDKProxyTests.java项目中  :  Controller - Service接口 - Proxy - InvocationHandler - ServiceImpl - Daojdk最重要的是 目标对象实现接口  实现兄弟类## 权限管理子系统  动吧旅游
菜单: sys_menus
角色: sys_roles
用户: sys_users--  用户 n:n 角色 n:n 菜单++  中间表: sys_ role_ menus   ,   sys_ user_ roles
部门: sys_depts--  部门 1:n 用户   n进行维护(外键 )   逻辑维护在n这一方
日志:sys_logs--  用户 1:n 日志> 权限框架 : shiro 用户深身份认证> 先做 菜单表 >>>>>     项目搭建父工程dbpms(pom)     dbpms-common    dbpms-admin公共  共性 特性>>>>>    1:nrole:  id name  user_id               user:  id username             user_role: id   user_id  role_id1             1                             1                                           1      1            12             1                                2                                           2      1            23             1                                3                                           3      2            11             2      这样不行#    创建 maven ( 父工程不继承 )> 父工程 管理依赖   pom.xml  <packaging>pom</packaging>  pom工程-*-  06-dbpms 只有pom.xml文件  ->- 06-dbpms-common   parent 06-dbpms   共性资源->- 06-dbpms-admin   依赖于06-dbpms-common   启动工程
>>>>  pom.xml
父工程:  06-dbpms 只有pom.xml文件  packaging-.-pomparent-.-spring-bootproperties 指定依赖版本dependenciesbuild  组件
通用工程:  06-dbpms-common   parent 06-dbpms
业务工程:  06-dbpms-admin   依赖于06-dbpms-common依赖于common  dependency-.-06-dbpms-common
>>>>>>>>>
> 启动工程 在admin
> application.yml   server datasource mybatis log>>>>    通用内容设计     对象 ####   2021-03-22  ----------------------------
# 通用Module设计
> 领域对象 pojo
> 注解对象
> 异常类
> 工具类
> 请求处理
# 业务实现   写在admin中
## 菜单
> 业务各种管理 , 管理内部的操作  菜单的展示  一级目录 二级目录 三级目录对菜单的操作 查询所有,查询树结构,根据id查询,新增,修改
> 表### 数据层
> 领域对象 pojo对象在三个层都有用到,  用来传递,接收数据 (接收客户端传递的数据参数, 数据库读到程序中 -返回给客户端)
* 对象 -对应数据库字段
* 序列化 和 反序列化序列化:指把java对象转换为字节序列的过程, 便于在网络传输或保存在本地文件反序列化: 指把字节序列恢复成java对象的过程,
* 实现Serializable接口   * 添加serialVersionUID      *存储数据的对象都实现此接口*在序列化与反序列化过程中会产生*各自的serialVersionUID*   为了序列化与反序列化相同的内容实现接口 为序列化与反序列化过程做标记,, serialVersionUID作为版本标识  反序列化时,相同则进行
> Dao逻辑
* 业务(方法)
> 映射 .xmljoin 和 left join??join 两个表中条件成立的数据       * 一级目录没有父目录但也要显示(显示所有内容, parentId只显示有的 使用left join)查询所有级别目录  c.parentId=p.id
### 业务层
> 接口方法
> 实现
* @Service
* @Autowired  注入dao接口
* @Transactional   事务处理- readOnly=false 增删改不能读- rollbackFor=RuntimeException.class  --运行时出异常回滚- isolation=Isolation.READ_COMMITTED 没有脏读
### controller
* Controller@RestController@RequestMapping("/menu/")
* 请求 post delete get put
* 参数 @RequestBody @PathVariable
* 响应   共性  JsonResult.java state message data
* 异常 3种   全局异常共性 GlobalExceptionHandler.java @RestControllerAdvice  @ExceptionHandler(RuntimeException.class)## 部门 Dept
> SysDept.java
> SysDeptDao.java
> SysDeptMapper.xml
> SysDeptService.java
> SysDeptServiceImpl.java
> SysDeptControllre.javactrl+f12 看方法####   2021-03-23  ----------------------------
# json序列化和反序列化一种广义的序列化和反序列化
json序列化: 对象转换为json字符串
json反序列化: json字符串转换为pojo对象wwwwh when(何时,什么业务),what(什么错误),where(错误出在哪里cause by),why(为什么错,程序可能错的在哪里),how(如何解决)序列化失败: 在转换时, 类型不匹配, 时间Date@Async SysLogServiceImpl.java  ??????@Async注解描述的方法为一个异步切入点方法,这个方法执行时底层会在新的线程中进行调用@Async注解描述的方法其返回值类型建议为void,假如为非void你需要对方法返回值类型进行设计,比方说方法声明为Future<Integer>,方法内部的返回值为 return new AsyncResult<Integer>(rows)## 角色
> 表 角色:菜单 n:n   需要中间表
> 难点, 添加()修改(权限菜单的展示(已经有的需要查出来)menuIds )### Dao
* SysRole.java SysRoleDao.java CheckBox.java(存储)      SysRoleMapper.xml
* SysRoleMenuDao.java SysRoleMenuMapper.xml>>SysRoleMapper.xml
* 查询(* name)
* 查询(id 以及管理的菜单id)
* 新增
* 更新
>>SysRoleMenuMapper.xml### Service
* SysRoleService.java> 各个方法的业务
* SysRoleServiceImpl.java### controllerpageCurrent 第几页pageSize 一页中最多有多少数据
* SysRoleController.java分页 PageUtil.java 需要获取 Request 过程提取到 ServletUtil.java提取共性                需要判断 分页的参数是不是空, 提取到StringUtil.java把分页放在JsonResult.java中 controller中执行方法更简便####   2021-03-24  ----------------------------
## 用户
### MD5密码加密算法MD5Tests.java
### Dao
> pojo
> User interface
> UserRole interface
> User .xml
> UserRole .xml
> service
> serviceImpl
> controller
笔记都在idea里面RequestBody只能使用一个   描述一个参数
@PathVariable可以使用多个  描述多个参数####   2021-03-25  ----------------------------
n:n 的关系维护方在 中间表
1:n 的关系维护方在 n表中
> 角色业务: 添加角色自身信息 -执行方法添加到数据库, 菜单授权 -添加角色菜单关系数据(先删除原有的关系,再添加新的关系数据)
> 查询用户 -用户自身信息, 用户角色信息, 菜单信息#-------------------------------------#
* 1. 判断 要添加的角色是否存在 添加的是role_id 根据id查询返回结果来 判断* 2. 查询用户 信息  角色  管理的菜单  部门select sr.name '角色',sm.name '菜单',u.username '姓名',u.email '邮箱',u.mobile '电话',sd.name '部门'from sys_users uleft join sys_user_roles sur on u.id = sur.user_idleft join sys_roles sr on sur.role_id = sr.idleft join sys_role_menus srm on sr.id = srm.role_idleft join sys_menus sm on srm.menu_id = sm.idleft join sys_depts sd on u.deptId = sd.idwhere username = 'laohu';/*根据姓名查询用户信息 放在users中 姓名查询角色信息 放在roles中 据role_id - 查角色id放在 user_roles 据user_id - 查用户id放在 users中 据姓名查询菜单信息 放在menus中 据role_id查询部门信息 放在depts中 据user_id.xml文件 dao接口 业务层接口 实现类user业务层把 各个部分整合在一起最终在user控制层 使用业务从层方法*/* 3. 查询权限select distinct permissionfrom sys_user_roles urjoin sys_role_menus rmjoin sys_menus mon ur.role_id=rm.role_id and rm.menu_id=m.idwhere ur.user_id=1and trim(m.permission)!='' and m.permission is not null
#-------------------------------------## shiro 权限控制框架       *shiro.apache.org*    [](http://shiro.apache.org/reference.html)
> shiro框架 添加依赖 需要写 Realms 其作用: 访问数据库    > 其他文件需要配置
> 两条线:  框架作用是: 用户的权限 认证和授权
*      认证: subject -> Security Manager -> Authenticator -> Realms
*      授权: subject -> Security manager -> Authorzer -> Realmssubject , 主题Security Manager , 安全管理Authenticator , 认证者Authorzer , 授权Pluggable Readlms , 可插入领域Session Manager , 会话管理Session DAO , 会话数据Cache Manager , 缓存管理Cryptography 密码学### 依赖
> 普通项目    shiro-spring
> springboot项目    shiro-spring-boot-web-starter需要Realm  创建Realm类### Realm类ShiroRealm.java 类   extends /*AuthenticatingRealm*/ AuthorizingRealm   认证  授权在启动类中添加 Realm 对象配置### 过滤规则哪些访问路径url 访问时 进行认证访问### 在 spring 的配置文件(application.yml)中,添加登录页面的配置
shiro: loginUrl: /login.html
权限   指定访问url跳转到指定页面## 认证
* 1. subject 把信息提交给 .login()方法     2.Security Manager  .login()方法
* 3. 把信息提交给一个方法 调用方法Authenticator  继承 Security Manager    4.他有认证策略
* 5. realms 从数据库中提取信息  进行比较
*
* 底层Shiro框架的授权流程:
* 控制层  调用   subject 的子类 调用 .login() 方法  提交给 SecurityManager
* SecurityManager将认证操作委托给认证对象Authenticator
* Authenticator将用户输入的信息传递给Realm
* Realm访问数据库 并封装返回
* Authenticator对返回的信息进行身份认证> 基于用户名查询    还没有传密码
> UsernamePasswordToken 令牌
######  笔记在idea中> 三个对象 subject SecurityManager Realm
> 一张网 认证流程  subject -> Security Manager -> Authenticator -> Realms -> Database   认证在Authenticator
> 两个token  subject中的 realm查数据时
> shiro框架  我们需要做的提数据和查数据## 断点看Shiro框架的过程 token# Cookie Session
> Cookie
* 如何记录客户端的用户信息   username=lvjing    请求页面时cookie会被添加到请求中
> Session
*
> 区别:
* Session是记录在服务端的,而Cookie是记录在客户端的。
## 登录成功后, 登录成功后的状态## 登录成功之后就可以访问了服务器可以拿到 用户登录之后的会话状态####   2021-03-25  ----------------------------
# 异常 没有的异常登录时给出提示
> 全局异常处理
* 打印日志
* 给出用户反馈  设置JsonResult的值  setState(0)  判断什么异常 e instanceof XxxException 给出相应反馈setMessage("错误提示")
> instanceof 模式匹配
* if(e instanceof Exception){}  如果e是这个类型的就抛出指定异常
* 类型为引用类型的表达式可以使用instanceof进行测试,以找出表达式的运行时值引用的对象类是否可以转换为其他引用类型
* if(object instanceof String){String a = (String)object}# 登录之后,关闭浏览器,再次就不用登录信息存在哪里
Client客户端
Web Server服务端HTTP无状态协议> 登录会生成值Cookie服务器端创建user 创建Session(id)会话   生成Cookie对象存储Session地址(JSESSIONID)返回给客户端   客户端存储在浏览器中客户端再次发起请求 会携带JSESSIONID 访问服务器  服务器 据JSESSIONID -> get session id -> session ->user
* Cookie存储在浏览器 服务端生成      周期:1.会话C 浏览器关闭后就结束  2.持久C 设置C周期                          类似于员工卡 会员机制
* Session存储在服务端 服务端生成     周期30分钟# 授权
* 1. shiro框架执行Dao层方法获取数据库中请求用户的权限    -数据层 定义方法 在数据库查询用户对菜单的权限
* 2. shiro框架查找@RequiresPermissions("sys:user:update")  注解并获取注解中的权限标识
* 3. 获取的权限标识 与 数据库中的菜单权限进行比较
*
* 底层Shiro框架的授权流程:
* Subject 调用方法checkPermission把用户需要的权限提交给 SecurityManager 信息来自哪里
> @RequiresPermissions("sys:user:update")  授权切入点方法  shiro框架提供告诉系统 此方法需要权限> 有些方法需要授权 有些不需要   AOP  -- 对判断用户有没有权限的动作封装  -> 底层查询到了所有的权限信息 判断请求是否包含在数据库查到内容里
* 授权逻辑   Shiro框架底层封装在AOP中的通知方法
* controller -> AopProxy -> AuthorizingMehtodInterceptor -> subject.checkPermisssion -> SecurityManager -> Authorize -> Realm> 查询时添加权限, 执行查询到的结果是, 登录用户的权限信息????
* 执行方法时, 两个查询, 1.注解的权限查询 封装在PageHelper中了  2.查询用户信息,没有封装到分页
+          解决1.: 把分页放在service实现类中执行,权限之后执行分页     业务层接口实现类控制层执行方法 改动大
+          解决2.: 权限放在controller控制, 注解方法控制端
+                      controller层在产生代理对象时 会把url的注解扔掉 --使用DefaultAdvisorAutoProxyCreator对象指定代理类的创建
* ++++整合的资源很多,有问题 Shiro PageHelper????      * ShiroDefaultAdvisorAutoProxyCreator在写业务层时  查询users返回值直接使用pageinfo 那权限注解就可以直接写在业务层,不需要很大改动>>>>>  获取登录用户
* String modifiedUser = ((SysUser)SecurityUtils.getSubject().getPrincipal()).getUsername();# 进阶    配置写在启动类中
> session配置
* SessionManager> 记住我
* 登录之前对token配置RememberMe   --token.setRememberMe(true);
* 写自己的cookie保存时间 7天> ???   重启服务后,再次直接访问user会让登录
* 原因: 重启的服务不能对原有的cookie解密, 并不是原有的cookie不管用
* 设置指定的key值, 每次cookie的解析都一样
* cManager.setCipherKey(Base64.decode("WGjHie9R114WBoCm3TAZ0g=="));> 授权缓存配置
* 置 Shiro 中自带的 CacheManager 对象,此对象可以通过 Cache 缓存授权时获取到权限信息,下次再访问授权方法时不需要再查用户权限,> @Bean
* 这个注解主要用在方法上,声明当前方法体中包含了最终产生 bean 实例的逻辑,方法的返回值是一个 Bean。这个 bean 会被 Spring 加入到容器中进行管理,默认情况下 bean 的命名就是使用了 bean 注解的方法名。@Bean 一般和 @Component 或者 @Configuration 一起使用。
*  @Bean(name = {"myUser", "yourUser"})public User user() {return new User;}> 修改密码=
* ####   2021-03-29  ----------------------------
# 04-notice-ss   公告业务系统   页面实现    添加,删除,修改
## 单体 前后端分离
## 1. 2. 3. 4. 5.页面架构 6.代码实现
* html呈现数据/css渲染数据/javascript动态效果/ 三剑客
* jquery/bootstrap(内置了html css js )  框架
* SPA (单页应用设计  single page web application)  :框架 一个body 多个div    -- 提高客户端与服务端通讯效率## 列表数据加载 呈现
> 通过ajax中的url请求服务端, 获取result(JsonResult)
> 对result进行处理 展示在页面中
jquery
ajax
循环 迭代数据呈现
tBody.empty() 清空
records.forEach() 迭代
tBody.append()在被选元素的结尾插入指定内容*  ???
> 1
跨端     : 就是平台 手机端, PC端
跨域     : 当一个请求url的协议(protocol)、域名(host)、端口(port)三者之间任意一个 与当前页面url不同即为跨域同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互
响应式  : 一个网站能兼容对个终端    通过各种尺寸的设备浏览网站获得良好的视觉效果的方法
> 2
request   请求
result      结果
response 响应
> 3
localStorage 浏览器本地存储name/value对 相当于MaplocalStorage的存储,读取,删除window.localStorage.setItem('key',value)   window.localStorage.setItem('key',JSON.stringiFy(object))把object转换为JSON字符串传入window.localStorage.getItem('key')            JSON.parse(window.localStorage.getItem('key'))把字符串转换为对象window.localStorage.removeItem('key')window.localStorage.clear()
> 4
button与input type="button" 的区别
在 button 元素内部,可以放置文本或图像。这是< button>与使用 input 元素创建的按钮的不同之处。< button> 控件提供了更为强大的功能和更丰富的内容
> 5
* 1. vue 已经3.0 (相比2.0大小减少50% 性能提高40%)element-ui 使用 vue2.0
* 2. bootstrap3 稳定      getbootstrap.com 5.0   bootcss.com 3# notice-jquery.html 页面实现
## 页面布局
> 标题
> 内容
> 内容列表
* 使用表格形式
* 标题thead为静态, 内容tbody使用jquery从服务端获取(初始内容为 数据正在加载中...colspan横向合并表格 )
> 分页(上一页,下一页)
* 上一页,当前页/所有页,下一页,输入页码,跳转
* 按钮给class值, 在实现按钮功能时获取按钮
> 代码编辑
## 查询内容呈现
> 通过ajax获取result   把获取的结果呈现在页面tbody中   ajax设置url success方法(如果服务端没有抛异常执行*1. 函数doHandleQureyResponseResult* 打印在页面)
> 服务端抛出异常,服务端捕获异常,     没有异常state=1,处理正确结果,执行*1.1 函数doHandleQueryOk*     捕获异常state=0执行*1.2 函数doHandleQueryError*
> 处理正常查询结果 把结果给tbody*1.1.1 函数doSetTableBodyRows*    分页查询*1.1.2函数doSetPagination*
> 设置tbody中的值, 获取tbody对象,清空原有内容,    迭代结果,获取每条(行)记录,把每行放在tbody后(方法append()  参数为每行记录中的每个元素) *1.1.1.0函数doCreateRow*
> 获取每行记录中的元素值 >处理异常查询结果
## 分页
> 添加点击事件
> 注册分页事件 $(".pagination").on("click",".pre,.next,.jump",doJumpToPage);
> 设置分页信息*1.1.2.0 函数doSetPagination*  --获取结果中的页码数和每页条数   --设置显示页数 1/3  --把页面数存在本地存储localStorage中set
> 执行点击事件函数   --获取class属性值  --获取当前页面值 current size  --ifelse 执行按钮点击 修改页码 pre next jump    --jump 获取输入的值  $("form input[name=pageCurrent]").val()
> 基于新的页码查询> 问题
* 点击上(下)一页  不能超出范围
* 跳转没有的页面给提示
* 跳转结束后,清空输入框中的内容
* 把在输入框,localStorage中获取的值强转为int类型进行比较
* 跳转指定页面  f5刷新显示第一页## 页面加载完成执行查询
> 页面加载函数
* 执行查询
* 注册分页####   2021-03-30  ----------------------------
?    result.data 中的数据哪来的  pages pageNum
?    params
?    ajax请求的属性什么意思
?    监听
*    模板字符串 console.log(`a1的值是${a1} 反引号)
*    反引号 模板字符串> 获取页面参数值
$("#typeId").val();
$("#noticeEditForm input:redio:checked").val();## 根据标题查询## 删除## 添加## 修改## 刷新## 小知识点* 刷新
* ####   2021-03-31  ----------------------------
# notice-vue
## vue/Axios/BootStrap
> Vue    ????
> Axios  ????
> Dom树 node节点 document object model 文档对象模型 (.html .xml) 在文档加载到内存中形成dom树
> js核心 EcmaScript
> Bom 浏览器对象 window
> th td th用在thead中 td用在tbody中
> let块作用域(方法内部)  var
# vue 渐进式框架  就是使用什么就加入什么
> npm(node.js)  nose包管理
> 添加vue.js 和 axios.min.js### 展示数据
### 分页
### 查询###
vue获取按钮中的id
谷歌快捷键设置####   2021-04-01  ----------------------------
# vue组件化   router# 跨域访问  (3种)
服务端 80
客户端 9000
> 1. controller层 @CrossOrigin描述类   缺点,1.没有这个类 2.进行了认证,执行中到不了controller
> 2. 基于WebMVCConfigurer接口重写addCorsMappings()方法  仅仅跨域的配置, 过滤器,优先级都没有
> 3. 配置类中 ,  通过FilterRegistrationBean对象进行过滤器
> 基于过滤器的配置
* 把优先级设置高一些> 前后端分离 前端后端不同的服务(url, 端口)  就有了跨域Cors
* ajax 异步加载,局部刷新> 客户端跨域
* 跨域代理Proxy
# 06-dbpms-ui
modules
index.html
login.htmlcookies

ssmpro-note相关推荐

  1. Paddle Release Note

    Paddle Release Note 重要更新 飞桨paddle框架2.0.0版本有如下重要更新: • 编程范式:默认开启动态图模式进行模型开发和训练,通过动转静的方式进行模型部署和训练加速.如果需 ...

  2. 机器学习与高维信息检索 - Note 7 - 核主成分分析(Kernel Principal Component Analysis,K-PCA)

    Note 7 - 核主成分分析(Kernel Principal Component Analysis) 核主成分分析 Note 7 - 核主成分分析(Kernel Principal Compone ...

  3. 机器学习与高维信息检索 - Note 6 - 核, 核方法与核函数(Kernels and the Kernel Trick)

    Note 6 核, 核方法与核函数 到目前为止,我们所讨论的机器学习算法的成功都依赖于对输入数据分布的假设.例如,PCA的效果越好,数据围绕线性子空间分布.或者在线性判别分析中,我们假设类的高斯分布, ...

  4. ADPRL - 近似动态规划和强化学习 - Note 10 - 蒙特卡洛法和时序差分学习及其实例 (Monte Carlo and Temporal Difference)

    Note 10 蒙特卡洛法和时序差分学习 Monte Carlo and Temporal Difference 蒙特卡洛法和时序差分学习 Note 10 蒙特卡洛法和时序差分学习 Monte Car ...

  5. 机器学习与高维信息检索 - Note 5 - (深度)前馈神经网络((Deep) Feedforward Neural Networks)及基于CVXOPT的相关实例

    Note 5 - (深度)前馈神经网络((Deep) Feedforward Neural Networks)及相关实例 5.1 FNN的定义和动机 粗略地说,前馈神经网络(FNN)是一种特殊的函数类 ...

  6. ADPRL - 近似动态规划和强化学习 - Note 8 - 近似策略迭代 (Approximate Policy Iteration)

    Note 8 近似策略迭代 Approximate Policy Iteration 近似策略迭代 Note 8 近似策略迭代 Approximate Policy Iteration 8.1 通用框 ...

  7. 机器学习与高维信息检索 - Note 4 - 主成分分析及其现代解释(Principal Component Analysis, PCA)及相关实例

    主成分分析及其现代解释 4. 主成分分析及其现代解释 Principal Component Analysis and Its Modern Interpretations 4.1 几何学解释 The ...

  8. ADPRL - 近似动态规划和强化学习 - Note 7 - Approximate Dynamic Programming

    Note 7 - 近似动态规划 Approximate Dynamic Programming 7. 近似动态规划 (Approximate Dynamic Programming) 7.1 近似架构 ...

  9. ADPRL - 近似动态规划和强化学习 - Note 6 - Mitigating the Curse of Dimensionality

    Note 6 Mitigating the Curse of Dimensionality 减轻维度诅咒 6. Mitigating the Curse of Dimensionality 减轻维度诅 ...

  10. ADPRL - 近似动态规划和强化学习 - Note 4 - Policy Iteration Algorithms

    Note 4 - Policy Iteration Algorithms 4. Policy Iteration Algorithms 补充:范数的性质 4.1 贪婪诱导策略的特性 (Properti ...

最新文章

  1. 高校开学需要重新分配宿舍!国家卫健委和教育部发布重要通知
  2. iOS 下配置XMPP 服务器openfire详解
  3. 基于分类任务的信号(EEG)处理
  4. Python 技巧篇-开头注释怎么写最好,开头注释需要包含什么,开头注释的重要性
  5. java精确测量文本高度_Android精确测量文本宽高及基线位置的方法
  6. 学习记录:CONCAT()
  7. 体制内工作了十几年,跳出来学嵌入式合适吗?
  8. jQuery的get()、map()、map().get().join()简单应用
  9. 430单片机实现三人投票表决器_关于STC51下载器串口免冷启动简单方案
  10. lock free(无锁并发)是什么
  11. 在系统编程ISP及在应用编程IAP
  12. 旁路电容、滤波电容、去耦电容的作用与应用原理详解
  13. 读《人脑连接组研究:脑结构网络和脑功能网络》
  14. 什么是RTK?GPS导航和RTK的基本原理有什么不同?
  15. 源码多多-Discuz x2.5 论坛防灌水机制分析和设置方法
  16. 排查和判断常见的服务器故障
  17. Day50 python 多表操作
  18. [译]用R语言做挖掘数据《七》
  19. 2021这份电子书单请收好(品类齐全)!
  20. javaweb项目接入CAS单点认证(含自身系统的三员过滤)

热门文章

  1. Android从零开始配置opencv+tensorflow进行人脸识别+口罩识别(二:opencv展示当前图像并作适当调整)
  2. android qq聊天背景图片,手机qq聊天背景图片【突破指南】
  3. AVFoundation 视频常用套路: 拍照聚焦、曝光、闪光灯,拍视频手电筒
  4. 什么是大数据,盘点国内最大用户(腾讯、阿里巴巴、百度、京东)数据公司分析
  5. 五款电竞选手最爱真无线蓝牙耳机,高续航随时随地畅玩手游
  6. 怎么给视频配音?教你四种简单好用的视频配音方法
  7. mysql cc攻击_CC攻击原理
  8. Unity URP 获取深度图
  9. 关于 Kotlin 静态代码检测工具 detekt 的说明
  10. windows comp命令比对两个文件内容