java 后端框架模块
JFinal框架
web.xml
--接管所有请求--com.jfinal.core.JFinalFilter
configClass设置配置文件
数据层
看着和c#比
sql还是硬编码能看到,只是帮你事先生成。
这个都没看到sql,感觉是用的时候再去生成。
Model
ModelA extends BaseModelA<ModelA> extends Model<M extends Model>
renderJson返回的时候处理过了。。
_MappingKit
model和table的对应,自动生成的。
--arp.addMapping("lamp_box", "id", Box.class);
Model操作
- 单个
不是ID的-return dao.findFirst("select * from lamp_user where username=? ", username); - list
这里是要写完整语句
c#是搭好结构,输入where,order等条件 ,这样能参数化字段值? - 分页
paginate(int pageNumber, int pageSize, String select, String sqlExceptSelect, Object... paras)
其中的参数含义分别为:当前页的页号、每页数据条数、sql语句的select部分、sql语句除了select以外的部分、查询参数。绝大多数情况下使用这个API即可。
c#里是要建存储过程,然后传入这个存储参数来完成 - 添加/修改/删除
c#这里时有个标记,填入后,然后再去判断修改/删除。
这里添加用ModelA.Save(),修改用ModelA.Update()
通用sql
DB类来执行,
DB.find,--Record来维持数据。
DB.quer--List<xx>来维持。
怎样访问这些数据?遍历Record之类的。
执行存储
Db.execute
感觉就是有model用的时候
数据结构用Collection<model>,方法用model.dao.xx
没有model时
数据结构用Collection<Record>,方法用Db.xx
语句组织
SqlPara
- 复杂的通过sqltemplate
先写好sql语句,
初始化时加入sqltemplate容器中arp.addSqlTemplate("/sqlTemplate/all.sql");
SqlPara sqlPara = Db.getSqlPara("lamp.getRole", para);
service层
这里没有用service层。
有什么要model添加数据库操作的,直接在model中添加方法。
有要执行的语句,直接在controller中执行。
但官方例子里还是建议弄一个service层来操作数据,不过没有IService层,直接class
controller
route配置url和controller的对应。
数据交互
返回Json对象
@Before({GET.class})
public void getLampInfo() {
Integer id = getParaToInt("id");
renderJson(Message.success(Device.dao.getDeviceInfo(id)));
}
返回List
public List<Role> getRoleByUid(Integer uid) {
Kv para = Kv.by("uid", uid);
SqlPara sqlPara = Db.getSqlPara("lamp.getRole", para);
return Role.dao.find(sqlPara);
}
复合对象
public Record getDeviceInfo(Integer id) {
SqlPara sqlPara = Db.getSqlPara("lamp.deviceInfo", id);
return Db.findFirst(sqlPara).removeNullValueColumns();
}
通用的record对象,不需要定义一个复合类来维护。
基类设计-abstract Controller
- request请求的<key,value>参数转为对象。
- 一种是 public void getPicMedias(@Para("") PageRequestBody requestBody) {}
可能是注解这里自动注入成对象
c#中也有自动转对象,但大部分还是用FormCollection - 一种是调用Dict dict = getBean(Dict.class, "");
通过反射,调用Class里的SetXXX方法来生成对象。
- 一种是 public void getPicMedias(@Para("") PageRequestBody requestBody) {}
CamelController继承了Controller
主要还是泛型的列表类序列化困难?
改写了getBean,
- 一是前端参数可能是驼峰命名,这里也修改属性名尝试一下。
- 一个是属性是List类型。
对应前端"medias[0].id","medias[1].id"这样的参数?
大概是List里面包含的也是一个类,
里面又递归调用,没看懂。
增加了getBean,这里用了获取 对象的数组
从JsonString到对象
用JSON库
单个对象-JSON.parseObject(Jsonstring,xxClass)
泛型列表-public static <T> T parseObject(String text, TypeReference<T> type, Feature... features)
这里用的第二种。
但request中并不是json格式,就正常的key,value。
先是转成hashmap,再转成jsonString。
转成hashmap类型
主要是list的处理。
obj[0].p1=v1,obj[0].p2=v2
转成
HashMap-map1
key value
obj arraylist
[0]--HashMap -map2
key-p1,value-v1
[1]....
...
这里比较绕,结构上多层嵌套,HashMap套ArrayList,ArrayList里又是HashMap
逻辑上
obj[0].p1看着只要分成两部分就行,这个用
for (int i = 0; i < subNames.length; i++)
不知道何意,是有多层属性x1.x2.x3=v1??
大概用layerMap先指向总的map1,put<obj,arraylist>后,再指向map2,put<p1,v1>
BaseController
争对数据库操作,封装了常用操作,增删改查
- 一种是Model本身的方法。如增加
getAddModel->GetBean 从paramter-model,model.save() - 一种是用到表名,再生成Sql来调用,如删除
这里用泛型获取到ModelClass, TableMapping对应到表名
view的对应
view的路径由三部分组成
String template = baseViewPath + viewPath + view
在configRoute中
baseViewPath--setBaseViewPath("/_view")。
viewPath--add("/", IndexController.class, "/index") 第三个参数
add("/project", ProjectController.class)没有第三个参数时,用第一个参数
在controller中
view--render("abc.html");也可以加路径
lamp中这里页面是放在webapp\page里
controller中render("/page/sensor.html");
前端引擎/布局
controller 设置传递对象。
setAttr("blogPage", service.paginate(getParaToInt(0, 1), 10));
前端用Enjoy引擎写就好
看着和c#差不多,定义模板,模板里预留好占位符。
页面引用模板。
路由
FrontRoutes
有些是/web/开头,有些是/lamp开头
add("/web/led", LoraLedController.class);
add("/lamp/box/led", BoxLedController.class);
拦截器Interceptor
拦截有多个层次粒度
- 全局controller拦截--在config中配置
- Routes拦截--没看到
- 类/方法的拦截
在前面加注解Before({LampAuthInterceptor.class})。可以加多个,逗号隔开 - 清除拦截
加注解clear
校验配置Validator
每个controller methord都要建一个类。看着好冗余
也是AOP注入,在controller调用前执行,不通过直接返回响应。
- 参数判断
可以controller.getPara(),controller.getBean(Box.class,"")获取后再判断。
也可以直接调用基类方法validateRequired("name", MSG_KEY, "name不能为空"); - 处理逻辑
这里走的是异常机制,
BaseValidator
try {
check(controller);
}catch (Exception e){
if(e instanceof ValidateException){
throw e;
}else {
addError(MSG_KEY,e.getMessage());
}
}
BoxValidator
Assert.notBlank(box.getName(),"name不能为空");
...
cn.hutool.core.lang.Assert
判断不成立就抛出异常,外层来捕获处理。
shiro
把认证的对象和流程又一个个弄成独立概念了。
搭起了框架。然后你就往口子里添材料,添实际判断流程,添回调流程。
输入认证信息与预留认证信息的匹配
字段的对应,这里好像是默认的,起规定的名字。
预留认证信息的获取--SecurityManager
来源多样
- ini文件。
Factory<SecurityManager> factory = new IniSecurityManagerFactory ("classpath:shiro.shiro.ini");
- 数据库表
获取对象实例。
SecurityManager instance = iniSecurityManagerFactory.getInstance();
输入认证信息-UsernamePasswordToken
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("woxbwo", "456");
SecurityUtils来组合调度。
- 一个承载预留认证信息对象
SecurityUtils.setSecurityManager(instance)。 - 一头承载输入认证信息的对象,相当于一个预设的"当前用户"。
Subject subject = SecurityUtils.getSubject();
对这个"当前用户"进行认证。
这里逻辑有点改变的感觉,
一般是对输入信息进行认证,然后生成一个“当前用户”
这里是用输入信息来认证这个预设的“当前用户"
subject.login(usernamePasswordToken);
拓展认证--角色,权限。
ini文件这里都是按默认格式写好。
直接就能通过subject对象来调用。
认证过程换到数据库语句。
这里权限的一整套集合叫做Realm。定义一个AuthorizingRealm
具体认证过程。
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
成功后加入role,Permissions
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
这里securityManager是在配置里设置,不用在代码里初始化,设置成自定义的realm
然后类似.net的GSAuth..这种注解哪些接口是要认证的。。
这里是集中到配置里。。
<!-- Shiro连接约束配置,即过滤链的定义 -->
<property name="filterChainDefinitions">
<value> /login=anon /admin*=authc /student=roles[teacher] /teacher=perms["user:create"] </value>
</property>
Session管理
Lamp代码中有很多不一样的
Subject subject = (new WebSubject.Builder(request, response)).buildWebSubject();
没有配置文件
那些过滤链,以及未通过的跳转不知道在哪里
通过注解 @Before({LampAuthInterceptor.class}) 调用 ShiroAuthInterceptor来认证。
A Realm is a "database" of usernames and passwords
that identify valid users of a web application (or set of web applications),
plus an enumeration of the list of roles associated with each valid user.
You can think of roles as similar to groups in Unix-like operating systems,
because access to specific web application resources is granted to all users possessing a particular role (rather than enumerating the list of associated usernames).
A particular user can have any number of roles associated with their username.
cron4j
定时任务,有个String cron参数来设置时间规则。
任务看着就是同步远程服务的状态值。
huiduService/sponService/ysyService
Quartz
看着是自定义的任务定时或者条件触发任务
TaskController
public void add(@Para("") TransferTask transferTask) {
Task task = transferTask.toTask();
taskService.addTask(task);
Quartz有触发功能
Swagger
API 添加注解,自动生成同步的在线文档
提供 Web 页面在线测试 API
内置一个web服务,访问后会列出文档信息,并能点击调用?