数据(struts2的值栈)+模板(html文件,vm文件,ftl文件)=输出文本
pss05-代码生成器+角色权限管理\资料\velocity-1.7\docs\developer-guide.html开发指南,代码
org.apache.velocity
velocity
1.6
package cn.itsource.pss;
import java.io.StringWriter;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.junit.Test;
/**
* 测试Velocity功能
*/
public class VelocityTest {
@Test
public void testVelocity01() throws Exception {
//创建模板应用上下文
VelocityContext context = new VelocityContext();
context.put("msg", "小张是个好同志");
//拿到相应的模板(需要设置好编码)
Template template = Velocity.getTemplate("temptest/hello.html","UTF-8");
//准备输出流
StringWriter writer = new StringWriter();
template.merge(context, writer);
System.out.println(writer);
}
@Test
public void testVelocity02() throws Exception {
//创建模板应用上下文
VelocityContext context = new VelocityContext();
context.put("msg", "小张是个好同志");
//拿到相应的模板(需要设置好编码)
Template template = Velocity.getTemplate("temptest/hello.html","UTF-8");
//准备输出流
File file = new File("temptest/helloNew.html");
FileWriter writer = new FileWriter(file);
template.merge(context, writer);
writer.close();
}
}
Insert title here
大伙都说:${msg}
/ /**
private static final String SRC = “src/main/java/”;
private static final String PACKAGE = “cn/itsource/pss/”;
private static final String TEST = “src/test/java /”;
private static final String WEBAPP = “src/main/webapp/”;
private String[] paths ={
SRC+PACKAGE+“query/”, SRC+PACKAGE+“repository/”, SRC+PACKAGE+“service/”,
SRC+PACKAGE+“service/impl/”, SRC+PACKAGE+“web/controller/”, TEST+PACKAGE+“service/”,
WEBAPP+“js/model/”,WEBAPP+“WEB-INF/views/domain/”
};
private String[] tempNames = {
“DomainQuery.java”,“DomainRepository.java”,“IDomainService.java”,
“DomainServiceImpl.java”,“DomainController.java”,“DomainServiceTest.java”,
“domain.js”,“domain.jsp”
};
private String[] domains = {“Dept”};
//生成相应的文件
@Test
public void testCreate() throws Exception{
//创建模板应用上下文
VelocityContext context = new VelocityContext();
//一.遍历所有的Domain
for (int i = 0; i < domains.length; i++) {
//1.1拿到大写的domain
String domainBig = domains[i];
//1.2拿到小写的domain
String domainSmall = domainBig.substring(0,1).toLowerCase() + domainBig.substring(1);
//System.out.println(domainBig);
//System.out.println(domainSmall);
//1.3设置上下文的替换名称
context.put("Domain",domainBig);
context.put("domain",domainSmall);
//二.遍历所有的路径
for (int j = 0; j < paths.length; j++) {
//2.1拿到相应的路径
String path =paths[j];
//2.2拿到相应的模板名称
String tempName = tempNames[j];
//2.3拼接回我们需要的位置文件
String realPath = (path + tempName).replaceAll("Domain",domainBig).replaceAll("domain",domainSmall);
//三.准备相应文件与模板进行组合
//3.1准备相应的文件(要生成的文件)
File file = new File(realPath);
// 如果父文件不存在,我们创建一个
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs();
}
//3.2拿到相应的模板(需要设置好编码)
Template template = Velocity.getTemplate("template/"+tempName,"UTF-8");
FileWriter writer = new FileWriter(file);
template.merge(context, writer);
writer.close();
}
}
}
创建出来后我们运行,会发现domain.js会报错。原因是js中有很多 , 而 这 些 ,而这些 ,而这些和Velocity中的$形成了冲突,我们可以使用以下这种办法来进行解决:
domain.js修改
顶部加上:#set( D = ′ D = ' D=′’ ) -> 为$显示设置一个变量
进行替换
$( -> ${D}(
$. -> ${D}.
先运行看效果,如果有问题,请先进行模板文件的修改,再重新生成。直到最后功能可以成功!(记住:有错先改模板)
完整代码如下(还解决了如果文件存在我们就不再覆盖的问题):
package cn.itsource.pss.common;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.junit.Test;
import java.io.File;
import java.io.FileWriter;
public class CreateCodeTest {
/**
* 确定修改的顺序(这个顺序你根据自己的习惯决定即可)
* 1.src/main/java/cn/itsource/pss/query/DomainQuery.java
* 2.src/main/java/cn/itsource/pss/repository/DomainRepository.java
* 3.src/main/java/cn/itsource/pss/service/IDomainService.java
* 4.src/main/java/cn/itsource/pss/service/impl/DomainServiceImpl.java
* 5.src/main/java/cn/itsource/pss/web/controller/DomainController.java
* 6.src/main/test/cn/itsource/pss/service/DomainServiceTest.java
* 7.src/main/webapp/js/model/domain.js
* 8.src/main/webapp/WEB-INF/views/domain/domain.jsp
*/
//准备拼接路径的常量,如果有更多文件有利于重复利用
private static final String SRC = "src/main/java/";
private static final String PACKAGE = "cn/itsource/pss/";
private static final String TEST = "src/main/test/";
private static final String WEBAPP = "src/main/webapp/";
//准备路径(拼接)
private String[] paths ={
SRC+PACKAGE+"query/", SRC+PACKAGE+"repository/", SRC+PACKAGE+"service/",
SRC+PACKAGE+"service/impl/", SRC+PACKAGE+"web/controller/", TEST+PACKAGE+"service/",
WEBAPP+"js/model/",WEBAPP+"WEB-INF/views/domain/"
};
//准备所有模板名称(和路径顺序一致)
private String[] tempNames = {
"DomainQuery.java","DomainRepository.java","IDomainService.java",
"DomainServiceImpl.java","DomainController.java","DomainServiceTest.java",
"domain.js","domain.jsp"
};
//准备要生成的Domain(有可能同时生成多个)
private String[] domains = {"Dept"};
//是否需要覆盖已经存在的文件 false代表不覆盖,一般就用这个
//true代表覆盖,危险操作
private static final boolean FLAG = false;
//生成相应的文件
@Test
public void testCreate() throws Exception{
//创建模板应用上下文
VelocityContext context = new VelocityContext();
//一.遍历所有的Domain
for (int i = 0; i < domains.length; i++) {
//1.1拿到大写的domain
String domainBig = domains[i];
//1.2拿到小写的domain
String domainSmall = domainBig.substring(0,1).toLowerCase() + domainBig.substring(1);
//System.out.println(domainBig);
//System.out.println(domainSmall);
//1.3设置上下文的替换名称
context.put("Domain",domainBig);
context.put("domain",domainSmall);
//二.遍历所有的路径
for (int j = 0; j < paths.length; j++) {
//2.1拿到相应的路径
String path =paths[j];
//2.2拿到相应的模板名称
String tempName = tempNames[j];
//2.3拼接回我们需要的位置文件
String realPath = (path + tempName).replaceAll("Domain",domainBig).replaceAll("domain",domainSmall);
//三.准备相应文件与模板进行组合
//3.1准备相应的文件(要生成的文件)
File file = new File(realPath);
// 如果文件存在,我们根据情况看是否需要覆盖
if (file.exists() && !FLAG){
return;
}
// 如果父文件不存在,我们创建一个
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs();
}
System.out.println(file.getAbsoluteFile()); //查看生成路径
//3.2拿到相应的模板(需要设置好编码)
Template template = Velocity.getTemplate("template/"+tempName,"UTF-8");
FileWriter writer = new FileWriter(file);
template.merge(context, writer);
writer.close();
}
}
}
}
EasyCode是基于IntelliJ IDEA Ultimate版开发的一个代码生成插件,主要通过自定义模板(基于velocity)来生成各种你想要的代码。通常用于生成Entity(domain)、Dao、Service、Controller。如果你动手能力强还可以用于生成HTML、JS、PHP等代码。理论上来说只要是与数据有关的代码都是可以生成的。
因为是基于Database Tool开发,所有Database Tool支持的数据库都是支持的。
包括如下数据库:
• 支持多表同时操作
• 支持同时生成多个模板
• 支持自定义模板
• 支持自定义类型映射(支持正则)
• 支持自定义附加列
• 支持列附加属性
• 所有配置项目支持分组模式,在不同项目(或选择不同数据库时),只需要切换对应的分组,所有配置统一变化。
功能 Easy Code 其他工具
自定义模板 支持 支持
多表生成 支持 支持
生成方式 无缝集成在项目中 部分工具需要复制粘贴
附加列 支持 不支持
附加列属性 支持 不支持
动态调试模板 支持 不支持
图形化界面 支持 部分支持
使用环境 仅限IDEA 支持各种形式
在线支持 后期扩展 不支持
自定义类型映射 支持 部分支持
全局变量 支持 不支持
##引入宏定义
$!define
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##使用宏定义设置回调(保存位置与文件后缀)
##注意:为了路径,我现在都从main的位置开始
#save("/main/java/cn/itsource/zx/domain", ".java")
##使用宏定义设置包后缀
#setPackageSuffix("domain")
##使用全局变量实现默认包导入
$!autoImport
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Table;
##使用宏定义实现类注释信息
#tableComment("实体类")
@Entity
@Table(name="$!{lowerTableInfo}")
public class $!{tableInfo.name} extends BaseDomain {
##实现列进行排除
#set($temp = $tool.newHashSet("id"))
#foreach($item in $temp)
#set($newList = $tool.newArrayList())
#foreach($column in $tableInfo.fullColumn)
#if($column.name!=$item)
##带有反回值的方法调用时使用$tool.call来消除返回值
$tool.call($newList.add($column))
#end
#end
##重新保存
$tableInfo.setFullColumn($newList)
#end
#foreach($column in $tableInfo.fullColumn)
#if(${column.comment})//${column.comment}#end
private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end
#foreach($column in $tableInfo.fullColumn)
##使用宏定义实现get,set方法
#getSetMethod($column)
#end
}
完成后可以查询生成代码,没有问题继续!
这个我们可以参考默认代码中的service等地方
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Query"))
##设置文件名
$!callback.setFileName($tool.append($tableName, ".java"))
##设置文件保存的位置(依然是从src开始)
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/cn/itsource/zx/query"))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##引入相应的包
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}query;
##使用全局变量实现默认包导入
$!autoImport
import cn.itsource.zx.domain.$!{tableInfo.name};
import com.github.wenhao.jpa.Specifications;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;
public class $!{tableInfo.name}Query extends BaseQuery {
##注:如果生成的表没有name,这里会报错,遇到这种情况请把它删除
private String name;
@Override
public Specification createSpecification() {
//根据条件把数据返回即可
return Specifications.<$!{tableInfo.name}>and()
.like(StringUtils.isNotBlank(name),"name", "%"+name+"%")
.build();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
其实代码都差不多,只需要把相应位置的名称替换了即可
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Repository"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/cn/itsource/zx/repository"))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##引入相应的包
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}repository;
import cn.itsource.zx.domain.$!{tableInfo.name};
public interface $!{tableInfo.name}Repository extends BaseRepository<$!{tableInfo.name},Long>{
}
##定义初始变量
#set($tableName = $tool.append("I",$tableInfo.name, "Service"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/cn/itsource/zx/service"))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##引入相应的包
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;
import cn.itsource.zx.domain.$!{tableInfo.name};
public interface I$!{tableInfo.name}Service extends IBaseService<$!{tableInfo.name},Long> {
}
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "ServiceImpl"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/cn/itsource/zx/service/impl"))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##引入相应的包
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service.impl;
import cn.itsource.zx.domain.$!{tableInfo.name};
import cn.itsource.zx.repository.$!{tableInfo.name}Repository;
import cn.itsource.zx.service.I$!{tableInfo.name}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class $!{tableInfo.name}ServiceImpl extends BaseServiceImpl<$!{tableInfo.name},Long> implements I$!{tableInfo.name}Service {
@Autowired
private $!{tableInfo.name}Repository $!{lowerTableInfo}Repository};
}
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "ServiceTest"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/test/java/cn/itsource/zx/service"))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##引入相应的包
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;
import cn.itsource.zx.domain.$!{tableInfo.name};
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
public class $!{tableInfo.name}ServiceTest extends BaseServiceTest {
@Autowired
private I$!{tableInfo.name}Service $!{lowerTableInfo}Service;
@Test
public void findAll(){
System.out.println($!{lowerTableInfo}Service);
System.out.println($!{lowerTableInfo}Service.getClass());
List<$!{tableInfo.name}> $!{lowerTableInfo}s = $!{lowerTableInfo}Service.findAll();
for ($!{tableInfo.name} $!{lowerTableInfo} : $!{lowerTableInfo}s) {
System.out.println($!{lowerTableInfo});
}
}
}
需要替换的太多,大家可以选拷备出去替换了后再重新进行操作
去掉多余的东西(如department相关与用户名验证功能)
##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Controller"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/cn/itsource/zx/web/controller"))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##引入相应的包
#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}web.controller;
import cn.itsource.zx.common.UiPage;
import cn.itsource.zx.domain. $!{tableInfo.name};
import cn.itsource.zx.query. $!{tableInfo.name}Query;
import cn.itsource.zx.service.I $!{tableInfo.name}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/$!{lowerTableInfo}")
public class $!{tableInfo.name}Controller extends BaseController {
@Autowired
private I$!{tableInfo.name}Service $!{lowerTableInfo}Service;
@RequestMapping("/index")
public String index() {
//根据配置,这里会跳到/WEB-INF/views/$!{lowerTableInfo}/$!{lowerTableInfo}.jsp页面
return "$!{lowerTableInfo}/$!{lowerTableInfo}";
}
//查询分页数据
@RequestMapping("/page")
@ResponseBody
public UiPage page($!{tableInfo.name}Query query){
return new UiPage($!{lowerTableInfo}Service.findPageByQuery(query));
}
//这里准备一个方法,所有方法执行前都会执行它
@ModelAttribute("edit $!{tableInfo.name}")
public $!{tableInfo.name} beforeEdit(Long id, String cmd){
//有id的时候-> 修改功能
if(id!=null && "update".equals(cmd)) {
$!{tableInfo.name} $!{lowerTableInfo} = $!{lowerTableInfo}Service.findOne(id);
//把这个要修改的关联对象设置为null,可以解决n-to-n的问题
return $!{lowerTableInfo};
}
return null;
}
//添加
@RequestMapping("/save")
@ResponseBody
public Map save($!{tableInfo.name} $!{lowerTableInfo}){
return saveOrUpdate($!{lowerTableInfo});
}
//修改
@RequestMapping("/update")
@ResponseBody
public Map update(@ModelAttribute("edit $!{tableInfo.name}") $!{tableInfo.name} $!{lowerTableInfo}){
return saveOrUpdate($!{lowerTableInfo});
}
//添加或者修改
private Map saveOrUpdate( $!{tableInfo.name} $!{lowerTableInfo}){
Map map = new HashMap<>();
try {
$!{lowerTableInfo}Service.save($!{lowerTableInfo});
map.put(SUCCESS, true);
} catch (Exception e) {
e.printStackTrace();
map.put(SUCCESS, false);
map.put("msg", e.getMessage());
}
return map;
}
/**
* 返回的结果:{SUCCESS:true,msg:"原因..."}
* @param id
* @return
*/
@RequestMapping("/delete")
@ResponseBody
public Map delete(Long id){
Map map = new HashMap<>();
try {
$!{lowerTableInfo}Service.delete(id);
map.put(SUCCESS, true);
} catch (Exception e) {
e.printStackTrace();
map.put(SUCCESS, false);
map.put("msg", e.getMessage());
}
return map;
}
}
##定义初始变量
#set($tableName = $tool.append($tableInfo.name))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##设置回调
$!callback.setFileName($tool.append($lowerTableInfo, ".jsp"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/webapp/WEB-INF/views/${lowerTableInfo}"))
##实现列进行排除
#set($temp = $tool.newHashSet("id"))
#foreach($item in $temp)
#set($newList = $tool.newArrayList())
#foreach($column in $tableInfo.fullColumn)
#if($column.name!=$item)
##带有反回值的方法调用时使用$tool.call来消除返回值
$tool.call($newList.add($column))
#end
#end
##重新保存
$tableInfo.setFullColumn($newList)
#end
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
$!{lowerTableInfo}管理
<%@include file="/WEB-INF/views/head.jsp" %>
##这里是遍历所有相应的字段
#foreach($column in $tableInfo.fullColumn)
$column.name
#end
注意:拷备Employee实现后删除多余的内容(如department与一些format代码)
##定义初始变量
#set($tableName = $tool.append($tableInfo.name))
##拿到首字母小写的表单
#set($lowerTableInfo = $tool.firstLowerCase($!{tableInfo.name}))
##设置回调
$!callback.setFileName($tool.append($lowerTableInfo, ".js"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/webapp/js/model"))
$(function () {
//这里我们把很多会常用到的元素进行一个抽取
var searchForm = $("#searchForm");
var $!{lowerTableInfo}Grid = $("#$!{lowerTableInfo}Grid");
var $!{lowerTableInfo}Dialog = $("#$!{lowerTableInfo}Dialog");
var $!{lowerTableInfo}Form = $("#$!{lowerTableInfo}Form");
//只要a标签中有data-method属性,咱们就给它添加事件
// 执行对应的itsource中的事件
$("*[data-method]").on("click",function () {
itsource[$(this).data("method")]();
})
window.itsource={
search:function () {
//需要先引入 jquery.jdirk.js 才可以使用这个方法
var params = searchForm.serializeObject();
$!{lowerTableInfo}Grid.datagrid('load',params);
},
add:function () {
//隐藏有data-save属性的元素
$("*[data-save]").show();
//禁用有data-save属性的input元素的验证功能
$("*[data-save] input").validatebox("enableValidation");
//弹出表单窗口
$!{lowerTableInfo}Form.form("clear");//清除数据
$!{lowerTableInfo}Dialog.dialog("center").dialog("open");
},
edit:function () {
//弹出表单窗口
//选中了某一条数据才删除
var row = $!{lowerTableInfo}Grid.datagrid("getSelected");
if(row) {
//隐藏有data-save属性的元素
$("*[data-save]").hide();
//禁用有data-save属性的input元素的验证功能
$("*[data-save] input").validatebox("disableValidation");
$!{lowerTableInfo}Form.form("clear");//清除数据
$!{lowerTableInfo}Dialog.dialog("center").dialog("open");
//为form加载数据
$("#$!{lowerTableInfo}Form").form("load",row);
}else{
$.messager.alert('提示信息','请选择一行再进行修改!','info');
}
},
del:function () {
//拿到选中的这条数据
var row = $!{lowerTableInfo}Grid.datagrid("getSelected");
if(row){
$.messager.confirm('确认框', '确定要狠心删除我么?', function(r){
if (r){
//进行删除
$.get("/$!{lowerTableInfo}/delete",{id:row.id},function (result) {
if(result.success){
$('#$!{lowerTableInfo}Grid').datagrid('reload');
}else{
//alert("删除失败");
$.messager.alert('提示信息','删除失败!,原因:'+result.msg,"error");
}
})
}
});
}else{
$.messager.alert('提示信息','请选择一行再进行删除!','info');
}
},
save:function () {
var url = "/$!{lowerTableInfo}/save";
var id = $("#$!{lowerTableInfo}Id").val();
if(id){
url = "/$!{lowerTableInfo}/update?cmd=update";
}
$!{lowerTableInfo}Form.form('submit', {
url:url,
onSubmit: function(){
//做验证
return $("#$!{lowerTableInfo}Form").form("validate");
},
success:function(data){
var result = JSON.parse(data);//转成相应的json数据
if(result.success) {
$('#$!{lowerTableInfo}Grid').datagrid('reload');
}else{
$.messager.alert('提示信息','操作失败!,原因:'+result.msg,"error");
}
$!{lowerTableInfo}Dialog.dialog('close');
}
})
}
}
})
权限有哪些? 我们的登录应该是什么样的? 为什么我们要使用框架来完成权限?
密码加密又是什么意思?
权限是什么
简单的说:就是说你能不能对系统做某一种操作!
一般我们分两种:登录认证 + 权限认证
以前咱们登录:成功后所有内容都可以访问!
权限认证:你登录成功后,是否有操作某一个功能的权限
登录的逻辑
没有登录的人,我们称它为游客
游客要有票(令牌:token【username,password】)才可以进入
—
我们进入相应的验证:
密码加密问题
把密码进行散列加密(Sha,MD5)
加密次数,加盐 以及我们如何判断登录
角色资源的认识