智销系统项目day4 - 代码生成器&权限的认识

文章目录

  • 1. 模板技术
    • 1.1 简介
    • 2.2 模板技术和jsp的异同
    • 2.3 Struts2的主题样式使用freemarker完成的
    • 2.4 模板技术怎样输出数据
    • 2.5 Velocity模板技术可以实现的功能
    • 2.6 pom.xml:添加jar文件
    • 1.7 Hello Velocity
      • 1.7.1 VelocityTest
      • 1.7.2 temptest /hello.html
  • 2. 代码生成器(自定义)
    • 2.1 开发步骤
    • 2.2 准备模板
    • 2.3 确定顺序
    • 2.4 准备路径等
    • 2.5 完成创建代码
    • 2.6 解决$冲突问题
    • 2.7 其它细节处理
  • 3. EasyCode
    • 3.1 官方说明
      • 3.1.1 EasyCode能做什么?
      • 3.1.2 使用环境
      • 3.1.3 支持的数据库类型
      • 3.1.4 功能说明:
      • 3.1.5 功能对比:
    • 3.2 使用手册
      • 3.2.1 安装
      • 3.2.2 添加数据源(已经学过,不做详细讲解)
      • 3.2.3 生成一个基本代码
    • 3.3 自定义模板生成
      • 3.3.1 新建一个分组
      • 3.3.2 模板的创建与位置问题
  • 4. 代码生成器模板
    • 4.1 Domain实体对象
    • 4.2 Query查询对象
    • 4.3 Repository数据层
    • 4.4 IXxxService业务层接口
    • 4.5 XxxServiceImpl
    • 4.6 Test基本测试生成
    • 4.7 XxxController:控制层
    • 4.8 xxx.jsp 页面展示
    • 4.9 Xxx.js
  • 5. 权限设计
    • 登录的逻辑 没有登录的人,我们称它为游客 游客要有票(令牌:token【username,password】)才可以进入

1. 模板技术

1.1 简介

velocity-1.6.3.jar 默认模板的后缀vm
freemarker-2.2.19.jar 默认模板的后缀ftl

2.2 模板技术和jsp的异同

第一次jsp执行流程:jsp转译为java文件,编译为class文件
第2-n次jsp(没有修改)执行流程:直接访问class文件
apache-tomcat-8.x\work\Catalina\localhost_\org\apache\jsp\WEB_002dINF\views\employee

2.3 Struts2的主题样式使用freemarker完成的

jsp页面数据显示一般都是使用struts的标签库,标签库的内部的处理就是使用freemarker

struts2-core-2.x.jar\template\simple项目使用主题


<constant name="struts.ui.theme" value="simple" />

2.4 模板技术怎样输出数据

数据(struts2的值栈)+模板(html文件,vm文件,ftl文件)=输出文本

pss05-代码生成器+角色权限管理\资料\velocity-1.7\docs\developer-guide.html开发指南,代码

2.5 Velocity模板技术可以实现的功能

动态页面静态化:xxx.html
在后台准备数据,在前台准备模板,通过IO把数据与模板合并,真正的生成一个html页面出来
用作发送邮件、短信模板
代码生成器(今天要完成的代码生成器)

2.6 pom.xml:添加jar文件


<dependency>
	<groupId>org.apache.velocitygroupId>
	<artifactId>velocityartifactId>
	<version>1.6version>
dependency>

1.7 Hello Velocity

1.7.1 VelocityTest

package com.zpx.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();
    }

}

1.7.2 temptest /hello.html


<html>
<head>
<meta charset="UTF-8">
<title>Insert title heretitle>
head>
<body>
大伙都说:${msg}
body>
html>

其它的功能我们可以参见咱们的PDF文档进行学习

2. 代码生成器(自定义)

咱们在写代码的时候,应该已经发现了,如果你还要做另外一个模块,那么它们的基础代码都差不多,虽然我们直接拷备过来修改使用也是可以的。但还是会觉得有点浪费时间,所以我们可以做一个自己生成基础代码的功能,然后我们直接生成,再添加其它的功能即可!

没有代码生成器的时候,如果添加部门模型domain,复制IDepartmentService,修改类名,ctrl+f,进行人工替换
而使用了代码生成器就是先定义好模板,然后使用代码自动修改类名,有代码参照模板进行指定内容自动替换
先用一个临时模型Dept,进行测试
注:写代码生成器前,先把项目进行备份,以免写出问题无法挽回!

2.1 开发步骤

  1. 准备模板(把每个模块需要改的地方确定好)
  2. 确定所有模板的生成顺序
  3. 确定所有模板的生成位置
  4. 确定要生成的基本功能的domain(Dept)
  5. 根据Domain名称与模板结合,在相应位置生成文件
  6. 解决如果父文件夹不存在的问题
  7. 解决如果文件已经存在的问题
  8. 排错(有错先改模板)

2.2 准备模板

我需要生成多少个文件,我就得准备多少个模板
把所有Employee对应的文件都拷备一份到相应的位置(并改名为Domain):
(注意:大写与小写的替换)

把模板中的文件进行修改
提示(大家要操作的时候小心小心再小心)
所有的(大写)Employee换成 D o m a i n 所 有 的 ( 小 写 ) e m p l o y e e 换 成 {Domain} 所有的(小写)employee换成 Domain()employee{domain}
只留下一个最基础的name字段,其它的多余功能全部去掉
注意(Employee中关于部门的操作都需要去掉)
替换的位置$不要值不要出现前后空格

2.3 确定顺序

/ /**

  • 确定修改的顺序(这个顺序你根据自己的习惯决定即可)
  • 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
    */

2.4 准备路径等

//准备拼接路径的常量,如果有更多文件有利于重复利用
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"
};

//准备要生成的Domain(有可能同时生成多个)
private String[] domains = {"Dept"};

2.5 完成创建代码

//生成相应的文件
@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();
        }
    }
}

2.6 解决$冲突问题

创建出来后我们运行,会发现domain.js会报错。原因是js中有很多 , 而 这 些 ,而这些 ,和Velocity中的$形成了冲突,我们可以使用以下这种办法来进行解决:
domain.js修改
顶部加上:#set( D = ′ D = ' D=’ ) -> 为$显示设置一个变量
进行替换
$( -> ${D}(
$. -> ${D}.

2.7 其它细节处理

先运行看效果,如果有问题,请先进行模板文件的修改,再重新生成。直到最后功能可以成功!(记住:有错先改模板)

完整代码如下(还解决了如果文件存在我们就不再覆盖的问题):

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();
            }
        }
    }
}

如果代码生成器生成的文件有问题(错误),找到错误,修改模板,重新生成 -> 一直到生成没有问题为止(慢慢调)

上面是咱们以前代码生成器的开发方案,现在咱们使用一个idea的插件(EasyCode)来完成相应的代码生成功能(前提是需要会Velocity的技术)。
对于EasyCode也是有相应文档可以查询(需要联网)!

3. EasyCode

它就是一个idea的插件

3.1 官方说明

EasyCode是基于IntelliJ IDEA开发的代码生成插件,支持自定义任意模板(Java,html,js,xml)。只要是与数据库相关的代码都可以通过自定义模板来生成。支持数据库类型与java类型映射关系配置。支持同时生成生成多张表的代码。每张表有独立的配置信息。完全的个性化定义,规则由你设置。
前提:你要会Velocity!!

3.1.1 EasyCode能做什么?

EasyCode是基于IntelliJ IDEA Ultimate版开发的一个代码生成插件,主要通过自定义模板(基于velocity)来生成各种你想要的代码。通常用于生成Entity(domain)、Dao、Service、Controller。如果你动手能力强还可以用于生成HTML、JS、PHP等代码。理论上来说只要是与数据有关的代码都是可以生成的。

3.1.2 使用环境

IntelliJ IDEA Ultimate版(172+)

3.1.3 支持的数据库类型

因为是基于Database Tool开发,所有Database Tool支持的数据库都是支持的。
包括如下数据库:

  1. MySQL
  2. SQL Server
  3. Oracle
  4. PostgreSQL
  5. Sqlite
  6. Sybase
  7. Derby
  8. DB2
  9. HSQLDB
  10. H2
    当然支持的数据库类型也会随着Database Tool插件的更新同步更新。

3.1.4 功能说明:

• 支持多表同时操作
• 支持同时生成多个模板
• 支持自定义模板
• 支持自定义类型映射(支持正则)
• 支持自定义附加列
• 支持列附加属性
• 所有配置项目支持分组模式,在不同项目(或选择不同数据库时),只需要切换对应的分组,所有配置统一变化。

3.1.5 功能对比:

功能 Easy Code 其他工具
自定义模板 支持 支持
多表生成 支持 支持
生成方式 无缝集成在项目中 部分工具需要复制粘贴
附加列 支持 不支持
附加列属性 支持 不支持
动态调试模板 支持 不支持
图形化界面 支持 部分支持
使用环境 仅限IDEA 支持各种形式
在线支持 后期扩展 不支持
自定义类型映射 支持 部分支持
全局变量 支持 不支持

3.2 使用手册

我们这只作一些简单的讲解,手册具体的部分可以参见给的 makejava-EasyCode 文档
https://gitee.com/makejava/EasyCode/wikis/pages

3.2.1 安装

在线安装,直接打开
智销系统项目day4 - 代码生成器&权限的认识_第1张图片
离线安装(先下载相应的zip包)
智销系统项目day4 - 代码生成器&权限的认识_第2张图片

3.2.2 添加数据源(已经学过,不做详细讲解)

智销系统项目day4 - 代码生成器&权限的认识_第3张图片
智销系统项目day4 - 代码生成器&权限的认识_第4张图片
智销系统项目day4 - 代码生成器&权限的认识_第5张图片

最主要的就是控制它的位置与内容

3.2.3 生成一个基本代码

使用dept为例:这个是最简单的测试!!
智销系统项目day4 - 代码生成器&权限的认识_第6张图片
我们这里只是生成一个最简单的实体类(当然,这个是使用它的自己原来的一个代码生成器模板,和我们最后想要的效果还有很大的差别!)

3.3 自定义模板生成

3.3.1 新建一个分组

咱们的代码生成器
智销系统项目day4 - 代码生成器&权限的认识_第7张图片

3.3.2 模板的创建与位置问题

智销系统项目day4 - 代码生成器&权限的认识_第8张图片
我们直接从原来模板中的entity中拷备过来,然后改成我们需要的代码即可!
注意:解决文件生成的位置问题:
模板代码的位置:
智销系统项目day4 - 代码生成器&权限的认识_第9张图片
生成时的路径位置:
智销系统项目day4 - 代码生成器&权限的认识_第10张图片
注:两个位置结合起来,最后才能把文件放到自己想要的地方

4. 代码生成器模板

4.1 Domain实体对象

##导入宏定义
$!define

##保存文件(宏定义)
#save("/main/java/com/zpx/domain", ".java")

##包路径(宏定义)
#setPackageSuffix("domain")

##自动导入包(全局变量)
$!autoImport
import javax.persistence.*;

##表注释(宏定义)
@Entity
@Table(name = "${tableInfo.obj.name}")
public class $!{tableInfo.name} extends BaseDomain {

#foreach($column in $tableInfo.otherColumn)
    #if(${column.comment})//${column.comment}#end

    private $!{tool.getClsNameByFullName($column.type)} $!{column.name};
#end

#foreach($column in $tableInfo.otherColumn)
    #getSetMethod($column)
#end

}

完成后可以查询生成代码,没有问题继续!

4.2 Query查询对象

这个我们可以参考默认代码中的service等地方

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Query"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/com/zpx/query"))


#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}query;

$!autoImport
import com.zpx.domain.$!{tableInfo.name};
import com.github.wenhao.jpa.Specifications;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.jpa.domain.Specification;

public class $!{tableName} extends BaseQuery {

    private String name;


    @Override
    public Specification createSpec(){
        
        Specification<$!{tableInfo.name}> spec = Specifications.<$!{tableInfo.name}>and()
                .like(StringUtils.isNotBlank(name),"name", "%"+name+"%")
                .build();
        return spec;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

4.3 Repository数据层

其实代码都差不多,只需要把相应位置的名称替换了即可

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Repository"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/com/zpx/repository"))


#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}repository;

$!autoImport
import com.zpx.domain.$!{tableInfo.name};

public interface $!{tableName} extends BaseRepository<$tableInfo.name,Long> {

}

4.4 IXxxService业务层接口

##定义初始变量
#set($tableName = $tool.append("I",$tableInfo.name, "Service"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/com/zpx/service"))


#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;

$!autoImport
import com.zpx.domain.$!{tableInfo.name};

public interface $!{tableName} extends IBaseService<$tableInfo.name,Long> {

}

4.5 XxxServiceImpl

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "ServiceImpl"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/com/zpx/service/impl"))


#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service.impl;

$!autoImport
import com.zpx.domain.$!{tableInfo.name};
import com.zpx.repository.$!{tableInfo.name}Repository;
import com.zpx.service.I$!{tableInfo.name}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class $!{tableName} extends BaseServiceImpl<$!{tableInfo.name},Long> implements I$!{tableInfo.name}Service {
    @Autowired
    private $!{tableInfo.name}Repository $!{tableInfo.obj.name}Repository;
}

4.6 Test基本测试生成

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "ServiceTest"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/test/java/com/zpx/service"))


#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}service;

import com.zpx.BaseSpringTest;
import com.zpx.domain.$!{tableInfo.name};
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class $!{tableInfo.name}ServiceTest extends BaseSpringTest {
    @Autowired
    private I$!{tableInfo.name}Service $!{tableInfo.obj.name}Service;

    @Test
    public void testFindAll()throws Exception{
        $!{tableInfo.obj.name}Service.findAll().forEach(e-> System.out.println(e));
    }

}

4.7 XxxController:控制层

需要替换的太多,大家可以选拷备出去替换了后再重新进行操作
去掉多余的东西(如department相关与用户名验证功能)

##定义初始变量
#set($tableName = $tool.append($tableInfo.name, "Controller"))
##设置回调
$!callback.setFileName($tool.append($tableName, ".java"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/java/com/zpx/web/controller"))


#if($tableInfo.savePackageName)package $!{tableInfo.savePackageName}.#{end}web.controller;

$!autoImport
import com.zpx.common.JsonResult;
import com.zpx.common.UIPage;
import com.zpx.domain.$!{tableInfo.name};
import com.zpx.query.$!{tableInfo.name}Query;
import com.zpx.service.I$!{tableInfo.name}Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
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.List;

@Controller
@RequestMapping("/$!{tableInfo.obj.name}")
public class $!{tableInfo.name}Controller extends BaseController {
    @Autowired
    private I$!{tableInfo.name}Service $!{tableInfo.obj.name}Service;
    @RequestMapping("/index")
    public String index(){
        //根据配置,这里会跳到/WEB-INF/views/$!{tableInfo.obj.name}/$!{tableInfo.obj.name}.jsp页面
        return "$!{tableInfo.obj.name}/$!{tableInfo.obj.name}";
    }
    /*@RequestMapping("/list")
    @ResponseBody
    public List<$!{tableInfo.name}> list(){
        return $!{tableInfo.obj.name}Service.findAll();
    }*/
    @RequestMapping("/page")
    @ResponseBody
    public UIPage<$!{tableInfo.name}> page($!{tableInfo.name}Query query){
        Page page = $!{tableInfo.obj.name}Service.findPageByQuery(query);
        //返回一个封装的对象
        return new UIPage(page);
    }
    //解决数据丢失
    /**
     *ModelAttribute:路径访问Controller的每个方法,都会先执行它里面的代码
     */
    @ModelAttribute("edit$!{tableInfo.name}")
    public $!{tableInfo.name} beforeEdit(Long id,String cmd){
        if (id!=null && "_update".equals(cmd)){
            //修改才走这个代码
            $!{tableInfo.name} db$!{tableInfo.name} = $!{tableInfo.obj.name}Service.findOne(id);
            //解决n-to-n的问题,把关联对象设置为空
            //employee.setDepartment(null);
            return db$!{tableInfo.name};
        }
        return null;
    }
    //删除功能
    @RequestMapping("/delete")
    @ResponseBody
    public JsonResult delete(Long id){
        try {
            $!{tableInfo.obj.name}Service.delete(id);
            return new JsonResult();
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(false,e.getMessage());
        }
    }
    //保存功能
    @RequestMapping("/save")
    @ResponseBody
    public JsonResult save($!{tableInfo.name} $!{tableInfo.obj.name}){
        try {
            $!{tableInfo.obj.name}Service.save($!{tableInfo.obj.name});
            return new JsonResult();
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(false,e.getMessage());
        }
    }
    //修改功能
    @RequestMapping("/update")
    @ResponseBody
    public JsonResult update(@ModelAttribute("edit$!{tableInfo.name}")$!{tableInfo.name} $!{tableInfo.obj.name}){
        try {
            $!{tableInfo.obj.name}Service.save($!{tableInfo.obj.name});
            return new JsonResult();
        } catch (Exception e) {
            e.printStackTrace();
            return new JsonResult(false,e.getMessage());
        }
    }
   
}

4.8 xxx.jsp 页面展示

##设置回调
$!callback.setFileName($tool.append($tableInfo.obj.name, ".jsp"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/webapp/WEB-INF/views/${tableInfo.obj.name}"))
<%--
  这是一个处理数据与查询的页面
  Created by IntelliJ IDEA.
  User: 86147
  Date: 2019/7/5
  Time: 11:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>智销系统</title>
    <%--页面引入--%>
    <%@include file="/WEB-INF/views/head.jsp" %>
    <%--引入js--%>
    <script src="/js/model/$!{tableInfo.obj.name}.js"></script>
</head>
<body>
<%--enableHeaderClickMenu=true列数据隐藏--%>
<%--onRowContextMenu:showMenu右键增删改--%>
<%--pagination:true分页条--%>
<%--数据表格--%>
    <table id="$!{tableInfo.obj.name}Grid" class="easyui-datagrid"
           data-options="url:'/$!{tableInfo.obj.name}/page',fitColumns:true
           ,singleSelect:true,fit:true
           ,pagination:true,toolbar:'#gridTools',onRowContextMenu:showMenu
">
        <thead>
        <%--sortable="true"自动排序--%>
        <tr>
            #foreach($column in $tableInfo.otherColumn)
            <th data-options="field:'$!{column.name}',width:100">$!{column.name}</th>
            #end
        </tr>
        </thead>
    </table>

    <%--grid顶部工具栏--%>
    <div id="gridTools" style="padding:5px;height:auto">
        <%--功能条--%>
        <div id="gridMenu" style="margin-bottom:5px">
            <a href="#" data-method="add" class="easyui-linkbutton" iconCls="icon-add" plain="true">添加</a>
            <a href="#" data-method="update" class="easyui-linkbutton" iconCls="icon-edit" plain="true">修改</a>
            <a href="#" data-method="del" class="easyui-linkbutton" iconCls="icon-remove" plain="true">删除</a>
        </div>
            <%--查询条--%>
        <form id="searchForm">
            名称: <input name="name" class="easyui-textbox" style="width:80px">
            <a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">搜索</a>
        </form>
    </div>

    <%--添加与修改的表单对话框--%>
    <div id="editDialog" class="easyui-dialog" title="功能编辑" style="width:400px;"
         data-options="iconCls:'icon-save',resizable:true,modal:true,closed:true">
        <form id="editForm" method="post">
            <input id="$!{tableInfo.obj.name}Id" type="hidden" name="id" />
            <table cellpadding="5">
                #foreach($column in $tableInfo.otherColumn)
                <tr>
                    <td>$!{column.name}:</td>
                    <td><input class="easyui-validatebox" type="text" name="$!{column.name}"
                               data-options="required:true"></input></td>
                </tr>
                #end
            </table>
        </form>
        <div style="text-align:center;padding:5px">
            <a href="javascript:void(0)" class="easyui-linkbutton" data-method="save">提交</a>
            <a href="javascript:void(0)" class="easyui-linkbutton" data-method="closeDialog">关闭</a>
        </div>
    </div>
</body>
</html>

4.9 Xxx.js

注意:拷备Employee实现后删除多余的内容(如department与一些format代码)

##设置回调
$!callback.setFileName($tool.append($tableInfo.obj.name, ".js"))
$!callback.setSavePath($tool.append($tableInfo.savePath, "/main/webapp/js/model"))
$(function () {
    //1.获取常用的一些组件
    //数据表格
    var $!{tableInfo.obj.name}Grid = $("#$!{tableInfo.obj.name}Grid");
    //查询条
    var searchForm = $("#searchForm");
    //添加修改功能框
    var editDialog = $("#editDialog");
    //功能框表单
    var editForm = $("#editForm");

    //2.绑定相应事件
    $("*[data-method]").on("click",function () {
        var methodName = $(this).data("method");
        window.itsource[methodName]();
    })

    itsource={
        search(){
            //拿到from表单里的所有值,封装为一个对象(需要用到jqery扩展功能)
            //serializeObject:拿到一个form中的所有数据,封装成json对象
            var params = searchForm.serializeObject();
            $!{tableInfo.obj.name}Grid.datagrid("load",params);
        },
        add(){
            $("*[data-edit] input").validatebox("enable");
            $("*[data-edit]").show();
            //0.每次打开时,清空from表单里的数据
            editForm.form("clear");
            //1.打开弹出框(每次打开时绝对居中)
            editDialog.dialog("center").dialog("open");
        },
        update(){
            //1.获取需要修改的那行数据
            let row = $!{tableInfo.obj.name}Grid.datagrid("getSelected");
            //2.如果没有选中,给出提示,后面的代码就不再执行了
            if (!row){
                $.messager.alert('警告','请选中后再操作!',"warning");
                return ;
            }
            //清空form数据
            editForm.form("clear");
            //让密码框失效且隐藏起来
            $("*[data-edit] input").validatebox("disable");
            $("*[data-edit]").hide();
            /*
            //把结果进行回显
            if (row.department){
                row["department.id"] = row.department.id;
            }
            */
            //清空后回显选中行数据
            editForm.form("load",row);
            //3.打开弹出框
            editDialog.dialog("center").dialog("open");
        },
        //保存功能
        save(){
            var url ="/$!{tableInfo.obj.name}/save";
            //获取id的值
            var $!{tableInfo.obj.name}Id = $("#$!{tableInfo.obj.name}Id").val();
            if ($!{tableInfo.obj.name}Id){
                url = "/$!{tableInfo.obj.name}/update?cmd=_update";
            }
            editForm.form('submit',{
                //提交的路径
                url:"/$!{tableInfo.obj.name}/save",
                //提交之前的操作
                onSubmit:function () {
                    //做一些检查,表单若有违规字段,则不予提交
                    //返回false可以组织提交
                    return $(this).form('validate');
                },
                //data : {success:true/false,msg:xxx} -> 字符串
                success:function (data) {
                    //需要将字符串的data数据转化为json类型
                    var result = JSON.parse(data);
                    if (result.success){
                        $!{tableInfo.obj.name}Grid.datagrid("reload");
                    }else {
                        $.messager.alert('错误',`保存失败! 原因是:${result.msg}`,"error");
                    }
                    //关闭弹出框
                    itsource.closeDialog();
                }
            });
        },
        del(){
            //1.拿到选中数据
            let row = $!{tableInfo.obj.name}Grid.datagrid("getSelected");
            //2.如果没有选中,给出提示,后面的代码就不再执行了
            if (!row){
                $.messager.alert('警告','请选中后再操作!',"warning");
                return ;
            }
            //3.选中后,弹出确认删除窗口
            $.messager.confirm('确认','您确认想要删除记录吗?',function(r){
                if (r){
                    //4.如果确认,则把id传到后台,后台删除数据
                    $.get("/$!{tableInfo.obj.name}/delete",{id:row.id},function (result) {
                        if (result.success){
                            //删除成功则重载行
                            $!{tableInfo.obj.name}Grid.datagrid("reload");
                        }else{
                            $.messager.alert('错误',`删除失败! 原因是:${result.msg}`,"error");
                        }
                    })
                }
            });

        },
        //关闭窗口
        closeDialog(){
            editDialog.dialog("close");
        }

    }
    
})

//右键增删改扩展
function showMenu(e, rowIndex, rowData) {

    //选中这个行
    $("#$!{tableInfo.obj.name}Grid").datagrid("selectRow",rowIndex);
    //第0个位置的面板不支持相应功能
    e.preventDefault();
    $('#gridMenu').menu('show', {
        left: e.pageX,
        top: e.pageY
    });
}


5. 权限设计

  • 权限是什么
    简单的说:就是说你能不能对系统做某一种操作!
    一般我们分两种:登录认证 + 权限认证
    以前咱们登录:成功后所有内容都可以访问!
    权限认证:你登录成功后,是否有操作某一个功能的权限
  • 登录的逻辑
    没有登录的人,我们称它为游客
    游客要有票(令牌:token【username,password】)才可以进入

  • 我们进入相应的验证:
  1. 判断用户名是否存在
  2. 判断密码是否正确
  3. 判断用户是否已经过期
  4. 其它错误(解释权归我们自己)
  • 两个问题:session不通过(SE系统)/密码不安全

  • 密码加密问题
    把密码进行散列加密(Sha,MD5)
    加密次数,加盐 以及我们如何判断登录

  • 角色资源的认识

你可能感兴趣的:(java)