响应式布局:
做好的产品能在pc端,手机,平板都能正常浏览
开发项目两种方式
1.自己从0开始写代码
2.在若依中下载拥有基础功能的源码
若依使用的mysql版本
mysql5.7
导入别人的项目如何操作
若依项目下载地址**:https://gitee.com/y_project/RuoYi-Vue.git**
可以使用揉一项目修改器修改项目的名字
1.下载前端依赖:在wolfcode-ui包中的控制台输入命令:npm install
2.里面修改redis的密码(没有密码),或者本机地址不是localhost,在启动的时候会出现创建不了bean的异常
3.修改配置文件中连接数据库的账号密码
pom.xml文件的内容解释
modules:
指定当前项目中有哪些子模块
dependencyManager:
管理子项目中的版本,里面的dependencies不能直接被继承
dependencies:
可以直接被继承
A子模块如何使用B子模块中的API?
将B模块打包,再在A项目中做依赖
caro2o-admin:后台管理项目,接口
caro2o-common:封装子项目中的公共代码工具类,常量,自定义异常
caro2o-framework:框架相关的代码(Spring AOP /Spring Security等)
caro2o-generator:代码生成器
caro2o-quertz:定时任务
caro2o-system:系统管理模块(service/mapper)
caro2o-ui:前端项目
idea中快速查找接口的名称:edit->find->find in files->输入请求的名称
recode:记录用户的信息
认证:验证码,账号密码
**前端拿token:**在sessionhistory中拿取
编写认证的流程
获取验证码:
1.前端发起请求:http://localhost/dev-api/captchaImage,使用代理去访问后端
2.生成验证码,并将验证码存储到redis中
3.可以给前端返回两种形式的的验证码,字符串和数字计算
登录时的login:
1.先进行验证码的比较,将验证码和用户名,uuid给validateCaptcha类
先通过传进来的uuid在redis中查这个code是否存在,若验证码存在则在比对两者是否匹配
若不正确就抛出自定义异常"CaptchaExpireException"
2.若验证码通过,前端传进来用户名和密码传给loginPreCheck类,再进行登录前置校验(看账户密码是否在合理的范围之内,是否在黑名单里面),
3.若账户和密码前置校验成功,就正式校验账号密码,将验证后的用户生成为令牌返回给前端,并放在上下文域
登录时的getInfo
1.使用 **permissionService.getRolePermission(user);**根据前端传进来的user查询用户的角色
若是管理员就有所有的权限,否则就通过userId查询用户具有的权限
2.使用**permissionService.getMenuPermission(user)**获取这个用户所有的菜单数据权限
若是管理员就拥有所有的权限
若不是管理员,就查询用户的权限,若权限不是空的,就根据权限id查询权限,menuService.selectMenuPermsByRoleId(role.getRoleId())
否则就根据用户id查询权限menuService.selectMenuPermsByUserId(user.getUserId()
在将所有的权限放在HashSet中
基本增删改查的流程
前端api:
前端封装的方法(增删改查)
分页查询的请求应该在什么时候发送:在vue实例创建好之后,created
前端使用vali进行表单的校验
点击按钮出现模态框
提交修改表单后就重新查询一遍
并有提示信息
…的作用:解构,将数据遍历出来
param:
name:1,
age:2
…param:得到里面所有的数据
后端:
分页相关的专门使用类进行封装,在TableDataInfo对象中
其他的在Ajaxesult对象中
分页查询,参数是在startPage()方法中获取到(request.getparameter("pageNo"))
mapper中sql的编写有所不同,里面的**set**用于数据的更新
代码生成
若依可以为我们生成基本的crud功能,步骤如下
1.在数据库中创建一张需要的表
2.在代码生成页面导入这个 表,并进行提交
3.选中这个表并点击生成按钮
4.里面会生成三个文件:main,vue,sql文件
5.在数据库中运行sql文件,
6.前端文件:将vue中的内容拷贝到前端中的文件中,
7.将main文件中mapper.xml,domain,mapper,service文件拷贝到caro2o-system文件中,将controller文件拷贝到caro2o-admin中
8.重新运行项目就能看到效果,但是表中没有数据
使用数据字典的数据
1.dicts: [‘sys_user_sex’],将其放在export default里面
2.在添加或者修改的地方添加下拉列表并遍历展示性别
<el-form-item label="学生性别">
<el-select v-model="form.gender" placeholder="请选择性别">
<el-option
v-for="dict in dict.type.sys_user_sex"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
3.在表格中如何展示数据字典的lable,将表格中的1展示成为"男",使用插值语法
使用的是标签,修改里面option和value的值
<el-table-column label="性别" align="center" prop="gender" >
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_user_sex" :value="scope.row.gender"/>
</template>
</el-table-column>
4.使用张三做测试来测试菜单和按钮的权限(zs,123456)
菜单:根据用户的id查到对应的菜单(sys_user_role,sys_role_menu,sys_menu)
没有权限的功能前端使用使用**v-hasPermi=[“权限表达式”]**进行权限功能的隐藏
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:student:add']"
>新增</el-button>
实体类中的BeaseEntity
封装了所有实体类相同的字段和方法
searchVale ,可以理解为关键字
creatBy
creatTIme
updateBy
uptateTime
params
过滤查询的条件参数:普通的参数,后端使用 实体类对象进行封装,(以前使用xxxQueryObjiect)
特殊的参数:如关键字等,可以使用searchValue或者params来接收
Controller的父类BaseController
前端传递发过来的日期,如何自动封装到实体对象中
@DateTimeFormate(pattern=“yyyy-MM-dd”)
将实体对象中的日期转换到json字符串中
@jsonFormat(pattern=“yyyy-MM-dd”)
@InitBinder
public void initBinder(WebDataBinder binder)
{
// Date 类型转换
binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
{
@Override
public void setAsText(String text)
{
setValue(DateUtils.parseDate(text));
}
});
}
会自动的匹配日期格式,如果匹配失败,400
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
统一异常处理
有全局的异常处理的包,可以直接调用,不用再自己去进行定义
ThreadLocal 的作用
线程的局部变量,不存在共享的问题,就不会存在多线程并发访问异常的情况出现
set方法:使用set方法往当前线程中添加局部变量,各个线程独享
get方法:获取当前线程的局部变量
remove:如果我们长时间将数据保存在内存中,会造成内存泄漏问题,应该手动删除,不要等GC回收,
国际化
**含义:**一套系统支持多个国家的语言
使用的是admin中的resource中的messages
会根据浏览器的语言环境自动切换配置文件适应不同的语言
线程池
创建线程和销毁线程非常耗时,所以提前创建好一批线程对象,放在内存中
一次创建重复利用的目的,更高效利用连接 对象
1.tomcat线程池
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# 连接数满后的排队数,默认为100
accept-count: 1000
threads:
# tomcat最大线程数,默认为200
max: 800.当前可以同时处理800条请求
min-spare: 100 ,初始化创建的线程数
#如果超过上限,就需要排队等待线程的释放
2.JDK线程池
比tomcat更好,防止无限制排队,节约内存
当任务数量大于核心线程数,队列数量超过指定数量,则创建新的线程,若超过队列的最大数量,就执行拒绝策略
@Configuration
public class ThreadPoolConfig
{
// 核心线程池大小,核心线程池:当前的线程,默认使用核心线程,不会自动销毁
private int corePoolSize = 50;
// 最大可创建的线程数,还能创建150个非核心线程
private int maxPoolSize = 200;
// 队列最大长度,若超过200个请求,则排队,排队数量若超过1000,则创建新的线程
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间:若核心线程对象,若超过300,则销毁
private int keepAliveSeconds = 300;
自己写一遍teacher的所有功能
前端
vue:
@keyup.enter.native:监听键盘事件,按下Enter是触发该事件
this.reset();重置表单中所有元素的值
this.resetForm(“form”);重置指定名称的表单元素
teacher.js:
里面封装的都是访问后端的方式,在index.vue中会进行引用
后端
需要在菜单列表中添加教师管理这个
创建doman,service,controller,mapper.xml文件
实体类中的**@Excel(name = “性别”)**:导出时生成excel表的表头
mapper接口和mapper.xml文件字节码不在同一目录,在application配置文件中进行扫描的路径
@PreAuthorize(“@ss.hasPermi(‘system:student:list’)”)
该注解表示当前方法需要进行权限校验,只有当前用户具有"system:student:list"权限才能够执行该方法,如用户没有该权限会抛出拒绝异常,阻止用户执行该方法
@ss.hasPermi:用于判断当前用户是否拥有指定的权限,返回的布尔值
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null">name,</if>
<if test="age != null">age,</if>
<if test="gender != null">gender,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null">#{name},</if>
<if test="age != null">#{age},</if>
<if test="gender != null">#{gender},</if>
</trim>
这两段代码并不重复,使用者这两段代码可以用于区分列名和列值,后续的维护和修改操作会更加容易,里面的**suffixOverrides=“,”**删除最后一个",",没有满足的条件的数据就不加,以前会添加一个null
@Log(title = "教师管理", businessType = BusinessType.UPDATE)
这是一个自定义注解,记录日志,在执行update操作是,记录该操作的业务类型和标题,一般配合AOP使用
看代码应该看哪些东西
做的是什么,怎么做的,例如:抽取方法