1.1 mp的代码生成器
1.2 guns的代码生成器
1.3 对当前角色进行授权操作
mp的代码生成器:mybatis-plus代码生成器,主要用于生成dao、model、mapper。详情请查看http://mp.baomidou.com/#/generate-code
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir("D:\\workspace\\guns\\guns-admin\\src\\main\\java");//这里写你自己的java目录
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setTypeConvert(new MySqlTypeConvert() {
// 自定义数据库表字段类型转换【可选】
@Override
public DbColumnType processTypeConvert(String fieldType) {
return super.processTypeConvert(fieldType);
}
});
dsc.setDriverName("com.mysql.jdbc.Driver");//数据库驱动
dsc.setUsername("root");//数据库用户名
dsc.setPassword("1234");//数据库密码
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/guns?characterEncoding=utf8");
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
//strategy.setTablePrefix(new String[]{"_"});// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
//重点:配置要对那张表进行生成代码操作
strategy.setInclude(new String[]{"my_order"});
mpg.setStrategy(strategy);
guns代码生成器:guns框架自带的代码生成器,用于生成controller、service + impl、js、前端html模板。详情请查看:https://gitee.com/naan1993/guns
当前admin用户启动项目后,新添加菜单:订单管理(一级)以及添加订单、修改订单、编辑订单三个二级菜单。将admin用户获得订单管理所有权限。
这里需要注意:生成的二级菜单的请求地址一定要和guns代码生成器生成的order.html中请求一致。原因是:
guns代码生成器生成的html模板中含有shiro权限管理的页面标签,所以应该给当前用户授权,否则看不到页面中的按钮。
@if(shiro.hasPermission("/order/add")){
<#button name="添加" icon="fa-plus" clickFun="Order.openAddOrder()"/>
@}
@if(shiro.hasPermission("/order/update")){
<#button name="修改" icon="fa-plus" clickFun="Order.openOrderDetail()" space="true"/>
@}
@if(shiro.hasPermission("/order/delete")){
<#button name="删除" icon="fa-plus" clickFun="Order.delete()" space="true"/>
@}
2.1 数据表建立
2.2 采用代码生成器生成项目骨架
2.3 实现订单管理的CURD
建立数据表:my_order
CREATE TABLE `my_order` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id' ,
`user` varchar(255) DEFAULT NULL COMMENT '下单人名称' ,
`place` varchar(255) DEFAULT NULL COMMENT '地点' ,
`goods` varchar(255) DEFAULT NULL COMMENT '商品名称' ,
`createtime` datetime DEFAULT NULL COMMENT '下单时间' ,
PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET = utf8;
通过代码生成器生成的代码结构为:
//mabatis-plus代码生成器
--dao
--mapping
MyOrderMapper.xml //映射文件
MyOrderMapper.java //接口文件
--model
MyOrder.java //pojo类
//guns代码生成器
--order
--controller
OrderController.java //控制层代码
--service
OrderService.java //业务层接口代码
-impl
OrderServiceImpl.java //业务层实现类代码
--static
--order.order
order.js //业务展示
order_info.js //业务提交
--WEB_INF
--order.order
order.html //业务展示页面模板
order_add.html //添加业务页面模板
order_edit.html //编辑业务页面模板
订单管理的CURD(详细介绍开发过程)
订单展示
1.坐标:order.js
前端页面展示订单基本信息,基本信息展示页面存放于order.html中,页面初始化逻辑存储在order.js中。我们需要对其内容改造。
需要注意:filed一定要对应数据库中表的字段名称!!!id字段由于数据库自增长,这里无需显示出来。
/**
* 初始化表格的列
*/
Order.initColumn = function () {
return [
{field: 'selectItem', radio: true},
{title: 'id', field: 'id', visible: false, align: 'center', valign: 'middle'},
/*
* title:需要显示的字段标题
* field:对应数据库字段名
* visible:字段是否可见
* */
{title: '下单人名称', field: 'user', visible: true, align: 'center', valign: 'middle'},
{title: '地点', field: 'place', visible: true, align: 'center', valign: 'middle'},
{title: '商品名称', field: 'goods', visible: true, align: 'center', valign: 'middle'},
{title: '下单时间', field: 'createtime', visible: true, align: 'center', valign: 'middle'},
];
};
2.坐标:OrderController.java
表格展示已经写好,我们需要完成业务逻辑,让数据库中的订单数据展示到前台页面上。
//注入service层订单接口
@Autowired
private MyOrderMapper myOrderMapper;
/**
* 获取订单业务列表
*/
@RequestMapping(value = "/list")
@ResponseBody
public Object list(String condition) {
//采用工具类对字符串搜索条件进行判空处理 -- 条件商品名称
if (ToolUtil.isNotEmpty(condition)) {
//采用mp的条件构造器:EntityWrapper 填充like查询条件 -- 注意要使用 like %x%
EntityWrapper myOrderEntityWrapper = new EntityWrapper<>();
myOrderEntityWrapper.like("goods",condition);
//将构造好的条件添加入查询,执行查询
List myOrders = myOrderMapper.selectList(myOrderEntityWrapper);
return myOrders;
} else {
List myOrders = myOrderMapper.selectList(null);
return myOrders;
}
}
注意:H+ 前端模板的使用,js初始化页面的配置,mp中条件构造器EntityWrapper的使用。
添加订单
1.操作流程:用户点击'添加'按钮,添加订单页面弹出,页面上包括需要用户填写的订单的基本信息,填写完成后,点击提交即可添加成功。
这里的添加、修改均采用的请求方式分两步:点击按钮时 + 提交表单时。如:/order_add + /order/add
坐标:OrderController.java
/**
* 跳转到添加订单业务 -- 点击按钮时
*/
@RequestMapping("/order_add")
public String orderAdd() {
return PREFIX + "order_add.html";
}
/**
* 新增订单业务 -- 提交表单时
*/
@RequestMapping(value = "/add")
@ResponseBody
public Object add(MyOrder myOrder) {
//添加对象判空处理 -- id自增无需设置,这里的order对象不可能为空 -- 前端已经通过js进行判断
if (null != myOrder) {
//补充设置下单时间字段
myOrder.setCreatetime(new Date());
}
//执行插入记录操作
Integer insert = myOrderMapper.insert(myOrder);
return super.SUCCESS_TIP;
}
遇到的问题:空表单可以添加成功,这是逻辑不允许的,我们需要在表单中添加判空验证。
2.修改order_info.js,加入表单提交时的判空验证。
坐标:order_info.js
/**
* 初始化订单业务详情对话框
*/
var OrderInfoDlg = {
orderInfoData : {},
//添加表单空输入提示 -- 对应input框
validateFields: {
user: {
validators: {
notEmpty: {
message: '用户名称不能为空'
}
}
},
place: {
validators: {
notEmpty: {
message: '地点不能为空'
}
}
},
goods: {
validators: {
notEmpty: {
message: '商品名称不能为空'
}
}
}
}
};
/*
* 初始化方法中加入表单验证
*/
$(function() {
Feng.initValidator("orderInfoForm", OrderInfoDlg.validateFields);
});
/*
* 验证数据是否为空
* */
OrderInfoDlg.validate = function () {
$('#orderInfoForm').data("bootstrapValidator").resetForm();
$('#orderInfoForm').bootstrapValidator('validate');
return $("#orderInfoForm").data('bootstrapValidator').isValid();
}
//最后在提交添加的方法中加入以下判断,目的是在点击提交时,判断是否进行了表单判空验证。
if (!this.validate()) {
return;
}
3.对订单添加表单命名id,因为js中对id进行了表单绑定。
坐标:order_add.html
修改订单
1.操作流程:用户选定一条订单信息后,点击'修改'按钮后,弹出订单修改的二级页面,表单形式,包含了用户需要修改的订单基本信息。用户修改后,点击提交即可修改成功。
这里的逻辑可以分成两部分:
根据选定订单进行订单查询展示 -- 查询
对选定订单进行修改提交 -- 更新
上文中已经提到了添加和修改操作都分两步进行处理的,这里的修改便是:/order_update + /order/update
/**
* 跳转到修改订单业务 -- 点击按钮时
*/
@RequestMapping("/order_update/{orderId}")
public String orderUpdate(@PathVariable Integer orderId, Model model) {
if (ToolUtil.isEmpty(orderId)) {
throw new BussinessException(BizExceptionEnum.REQUEST_NULL);
}
//根据从请求中获取的orderId进行查询
MyOrder order = myOrderMapper.selectById(orderId);
//将查询到的对象设置到页面中
model.addAttribute("order", order);
return PREFIX + "order_edit.html";
}
2.配置order_edit.html页面接受order对象,并进行展示。
<#input id="user" name="用户名称" value="${order.user}" underline="true"/>
<#input id="place" name="地点" value="${order.place}" underline="true"/>
<#input id="goods" name="商品名称" value="${order.goods}" underline="true"/>
3.展示订单修改页面后,用户更改订单相应数据后点击提交按钮。请求/order/update,这里有一个springmvc的对象验证问题,稍后总结。
/**
* 修改订单业务 -- 点击提交时
*/
@RequestMapping(value = "/update")
@ResponseBody
public Object update(@Validated MyOrder order) {
//System.out.println(order.toString());
if (ToolUtil.isNotEmpty(order)){
myOrderMapper.updateById(order);
}
return super.SUCCESS_TIP;
}
4.当我们提交修改后的表单时候,我们也希望用户置空的字段是无法进行提交成功的。因此在order_info.js文件中添加表单置空验证。
坐标:order_info.js
if (!this.validate()) {
return;
}
订单删除
1.操作流程:用户选定订单信息后,点击删除按钮即可删除选定的订单数据。
坐标:OrderController.java
/**
* 删除订单业务
*/
@RequestMapping(value = "/delete")
@ResponseBody
public Object delete(@RequestParam("orderId") Integer orderId) {
Integer deleteOrderId = myOrderMapper.deleteById(orderId);
return SUCCESS_TIP;
}
总结问题
1.代码生成器的基本使用
2.mp中BaseMapper的学习,封装了基本的CURD操作。
3.mp中的EntityWrapper条件构造器的使用。
4.关于请求路径中参数的获取。
@RequestParam("param"):data域中获取参数,参数要对应。
@PathVariable("param"):url中获取参数,参数也要对应。
5.@Validated和@Valid区别。
Spring Validation验证框架对参数的验证机制提供了@Validated(Spring's JSR-303规范),javax提供了@Valid(标准JSR-303规范),配合BindingResult可以直接提供参数验证结果。
限制
说明
@Null
限制只能为null
@NotNull
限制必须不为null
@AssertFalse
限制必须为false
@AssertTrue
限制必须为true
@DecimalMax(value)
限制必须为一个不大于指定值的数字
@DecimalMin(value)
限制必须为一个不小于指定值的数字
@Digits(integer,fraction)
限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future
限制必须是一个将来的日期
@Max(value)
限制必须为一个不大于指定值的数字
@Min(value)
限制必须为一个不小于指定值的数字
@Past
限制必须是一个过去的日期
@Pattern(value)
限制必须符合指定的正则表达式
@Size(max,min)
限制字符长度必须在min到max之间
@Past
验证注解的元素值(日期类型)比当前时间早
@NotEmpty
验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank
验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email
验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
举例说明:
@Valid:package=javax.validation.Valid 不提供分组校验功能。
//首先需要在实体类的相应字段上添加用于充当校验条件的注解
@NotBlank(message = "角色名不能为空")
private String rolename;
//在controller层的方法的要校验的参数上添加@Valid注解,并且需要传入BindingResult对象,用于获取校验失败情况下的反馈信息。
@RequestMapping("/add")
@ResponseBody
public Role addRole(@Valid Role role, BindingResult bindingResult) {
//如果校验失败,打印反馈信息
if (bindingResult.hasErrors()) {
//打印相应属性上添加的message内容
System.out.println(bindingResult.getFieldError().getDefaultMessage());
return null;
}
return roleMapper.addRole(role);
}
@Validated:package=javax.validation 是对@Valid的一次封装,提供分组校验功能。
当一个实体类需要多种验证方式的时候,可以通过groups进行验证条件的分组。
定义分组接口类:
public interface Valid1() {
//...
}
public interface Valid2() {
//...
}
实体类属性:
1. 不分配groups,默认每次都要进行验证。
2. 对一个实体类参数需要多种验证方式的时候可以进行不同分组。
@NotBlank(message = "角色名不能为空", groups = {Valid1.class})
@Size(min = 3,max = 8, message = "长度不符合要求", groups = {Valid2.class})
private String rolename;
@NotNull(message = "年龄不能为空")
private int age;
控制层:
1. @Validated中没有添加groups属性时候(@validated Role role),所有已分组的实体属性将不会进行验证。
2. @Validated中添加groups属性时候(@validated({Group.class}) Role role),会对已分组的实体属性进行验证。
3. 关于组排序问题:默认情况下,不同组别的约束验证是无序的,但是在某些情况下,约束验证的顺序却很重要。
例:rolename属性,只有先进行判空验证后,才会长度的校验。这两个校验注解分别属于不同的组别,所以应该统一管理,并进行组排序。
//采用@GroupSequence注解进行组排序和组管理。
@GroupSequence({Valid1.class, Valid2.class})
public interface Group {
//...
}
此时,上一条中的@validated({Group.class}) Role role的意义就清晰了。
@RequestMapping("/add")
@ResponseBody
public Role addRole(@validated Role role, BindingResult bindingResult) {
//如果校验失败,打印反馈信息
if (bindingResult.hasErrors()) {
//打印相应属性上添加的message内容
System.out.println(bindingResult.getFieldError().getDefaultMessage());
return null;
}
return roleMapper.addRole(role);
}
提示:@NotNull、@NotEmpty和@NotBlank区别
@NotEmpty 用在集合类上面
@NotBlank 用在String上面
@NotNull 用在基本类型上面
8/2/2018 7:20:38 PM