基于JFinal完成一个简单的学生信息管理系统

 

 

 

 项目列表

 

 按照图中顺序从上往下

package com.demo.blog;

import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.core.Controller;
import com.jfinal.core.Path;
import com.demo.common.model.Blog;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * 所有 sql 与业务逻辑写在 Service 中,不要放在 Model 中,更不
 * 要放在 Controller 中,养成好习惯,有利于大型项目的开发与维护
 */
@Path("/blog")
@Before(BlogInterceptor.class)
public class BlogController extends Controller {
    
    @Inject
    BlogService service;
    
    public void index() {
        setAttr("blogPage", service.paginate(getParaToInt(0, 1), 10));
        render("blog.html");
    }
    
    public void add() {
    }
    
    /**
     * save 与 update 的业务逻辑在实际应用中也应该放在 serivce 之中,
     * 并要对数据进正确性进行验证,在此仅为了偷懒
     */
    @Before(BlogValidator.class)
    public void save() {
        getBean(Blog.class).save();
        redirect("/blog");
    }
    
    public void edit() {
        setAttr("blog", service.findById(getParaToInt()));
    }
    
    /**
     * save 与 update 的业务逻辑在实际应用中也应该放在 serivce 之中,
     * 并要对数据进正确性进行验证,在此仅为了偷懒
     */
    @Before(BlogValidator.class)
    public void update() {
        getBean(Blog.class).update();
        redirect("/blog");
    }
    
    public void delete() {
        service.deleteById(getParaToInt());
        redirect("/blog");
    }
}
package com.demo.blog;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * BlogInterceptor
 * 此拦截器仅做为示例展示,在本 demo 中并不需要
 */
public class BlogInterceptor implements Interceptor {
    
    public void intercept(Invocation inv) {
        System.out.println("Before invoking " + inv.getActionKey());
        inv.invoke();
        System.out.println("After invoking " + inv.getActionKey());
    }
}
package com.demo.blog;

import com.demo.common.model.Blog;
import com.jfinal.plugin.activerecord.Page;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * BlogService
 * 所有 sql 与业务逻辑写在 Service 中,不要放在 Model 中,更不
 * 要放在 Controller 中,养成好习惯,有利于大型项目的开发与维护
 */
public class BlogService {
    
    /**
     * 所有的 dao 对象也放在 Service 中,并且声明为 private,避免 sql 满天飞
     * sql 只放在业务层,或者放在外部 sql 模板,用模板引擎管理:
     *             https://jfinal.com/doc/5-13
     */
    private Blog dao = new Blog().dao();
    
    public Page<Blog> paginate(int pageNumber, int pageSize) {
        return dao.paginate(pageNumber, pageSize, "select *", "from blog order by id asc");
    }
    
    public Blog findById(int id) {
        return dao.findById(id);
    }
    
    public void deleteById(int id) {
        dao.deleteById(id);
    }
}
package com.demo.blog;

import com.demo.common.model.Blog;
import com.jfinal.core.Controller;
import com.jfinal.validate.Validator;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * BlogValidator.
 */
public class BlogValidator extends Validator {
    
    protected void validate(Controller controller) {
        validateRequiredString("blog.title", "titleMsg", "请输入Blog标题!");
        validateRequiredString("blog.content", "contentMsg", "请输入Blog内容!");
    }
    
    protected void handleError(Controller controller) {
        controller.keepModel(Blog.class);
        
        String actionKey = getActionKey();
        if (actionKey.equals("/blog/save"))
            controller.render("add.html");
        else if (actionKey.equals("/blog/update"))
            controller.render("edit.html");
    }
}
package com.demo.common.model.base;

import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.IBean;

/**
 * Generated by JFinal, do not modify this file.
 */
@SuppressWarnings("serial")
public abstract class BaseBlog<M extends BaseBlog<M>> extends Model<M> implements IBean {

    /**
     * id注释
     */
    public void setId(java.lang.Integer id) {
        set("id", id);
    }
    
    /**
     * id注释
     */
    public java.lang.Integer getId() {
        return getInt("id");
    }
    
    /**
     * title注释
     */
    public void setTitle(java.lang.String title) {
        set("title", title);
    }
    
    /**
     * title注释
     */
    public java.lang.String getTitle() {
        return getStr("title");
    }
    
    /**
     * content注释
     */
    public void setContent(java.lang.String content) {
        set("content", content);
    }
    
    /**
     * content注释
     */
    public java.lang.String getContent() {
        return getStr("content");
    }
    
}
package com.demo.common.model;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import javax.sql.DataSource;
import com.demo.common.DemoConfig;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.generator.Generator;
import com.jfinal.plugin.activerecord.generator.TypeMapping;
import com.jfinal.plugin.druid.DruidPlugin;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * 在数据库表有任何变动时,运行一下 main 方法,极速响应变化进行代码重构
 */
public class _JFinalDemoGenerator {
    
    public static DataSource getDataSource() {
        DruidPlugin druidPlugin = DemoConfig.createDruidPlugin();
        druidPlugin.start();
        return druidPlugin.getDataSource();
    }
    
    public static void main(String[] args) {
        // model 所使用的包名 (MappingKit 默认使用的包名)
        String modelPackageName = "com.demo.common.model";
        
        // base model 所使用的包名
        String baseModelPackageName = modelPackageName + ".base";
        
        // base model 文件保存路径
        String baseModelOutputDir = System.getProperty("user.dir")
                + "/src/main/java/" + baseModelPackageName.replace('.', '/');
        
        System.out.println("输出路径:"+ baseModelOutputDir);
        
        // model 文件保存路径 (MappingKit 与 DataDictionary 文件默认保存路径)
        String modelOutputDir = baseModelOutputDir + "/..";
        
        // 创建生成器
        Generator generator = new Generator(getDataSource(), baseModelPackageName, baseModelOutputDir, modelPackageName, modelOutputDir);
        
        // 配置是否生成备注
        generator.setGenerateRemarks(true);
        
        // 设置数据库方言
        generator.setDialect(new MysqlDialect());
        
        // 设置是否生成链式 setter 方法,强烈建议配置成 false,否则 fastjson 反序列化会跳过有返回值的 setter 方法
        generator.setGenerateChainSetter(false);
        
        // 添加不需要生成的表名到黑名单
        generator.addBlacklist("adv");
        
        // 设置是否在 Model 中生成 dao 对象
        generator.setGenerateDaoInModel(false);
        
        // 设置是否生成字典文件
        generator.setGenerateDataDictionary(false);
        
        // 设置需要被移除的表名前缀用于生成modelName。例如表名 "osc_user",移除前缀 "osc_"后生成的model名为 "User"而非 OscUser
        generator.setRemovedTableNamePrefixes("t_");
        
        // 将 mysql 8 以及其它原因之下生成 jdk 8 日期类型映射为 java.util.Date,便于兼容老项目,也便于习惯使用 java.util.Date 的同学
        TypeMapping tm = new TypeMapping();
        tm.addMapping(LocalDateTime.class, Date.class);
        tm.addMapping(LocalDate.class, Date.class);
        // tm.addMapping(LocalTime.class, LocalTime.class);        // LocalTime 暂时不变
        generator.setTypeMapping(tm);
        
        // 生成
        generator.generate();
    }
}
package com.demo.common.model;

import com.jfinal.plugin.activerecord.ActiveRecordPlugin;

/**
 * Generated by JFinal, do not modify this file.
 * <pre>
 * Example:
 * public void configPlugin(Plugins me) {
 *     ActiveRecordPlugin arp = new ActiveRecordPlugin(...);
 *     _MappingKit.mapping(arp);
 *     me.add(arp);
 * }
 * </pre>
 */
public class _MappingKit {
    
    public static void mapping(ActiveRecordPlugin arp) {
        arp.addMapping("blog", "id", Blog.class);
    }
}
package com.demo.common.model;

import com.demo.common.model.base.BaseBlog;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * Blog model.
 * 数据库字段名建议使用驼峰命名规则,便于与 java 代码保持一致,如字段名: userId
 */
@SuppressWarnings("serial")
public class Blog extends BaseBlog<Blog> {
    
}
package com.demo.common;

import com.demo.common.model._MappingKit;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.server.undertow.UndertowServer;
import com.jfinal.template.Engine;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * API 引导式配置
 */
public class DemoConfig extends JFinalConfig {
    
    static Prop p;
    
    /**
     * 启动入口,运行此 main 方法可以启动项目,此 main 方法可以放置在任意的 Class 类定义中,不一定要放于此
     */
    public static void main(String[] args) {
        UndertowServer.start(DemoConfig.class);
    }
    
    /**
     * PropKit.useFirstFound(...) 使用参数中从左到右最先被找到的配置文件
     * 从左到右依次去找配置,找到则立即加载并立即返回,后续配置将被忽略
     */
    static void loadConfig() {
        if (p == null) {
            p = PropKit.useFirstFound("demo-config-pro.txt", "demo-config-dev.txt");
        }
    }
    
    /**
     * 配置常量
     */
    public void configConstant(Constants me) {
        loadConfig();
        
        me.setDevMode(p.getBoolean("devMode", false));
        
        /**
         * 支持 Controller、Interceptor、Validator 之中使用 @Inject 注入业务层,并且自动实现 AOP
         * 注入动作支持任意深度并自动处理循环注入
         */
        me.setInjectDependency(true);
        
        // 配置对超类中的属性进行注入
        me.setInjectSuperClass(true);
    }
    
    /**
     * 配置路由
     */
    public void configRoute(Routes me) {
        // 使用 jfinal 4.9.03 新增的路由扫描功能
        me.scan("com.demo.");
    }
    
    public void configEngine(Engine me) {
        me.addSharedFunction("/common/_layout.html");
        me.addSharedFunction("/common/_paginate.html");
    }
    
    /**
     * 配置插件
     */
    public void configPlugin(Plugins me) {
        // 配置 druid 数据库连接池插件
        DruidPlugin druidPlugin = new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password"));
        me.add(druidPlugin);
        
        // 配置ActiveRecord插件
        ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
        // 所有映射在 MappingKit 中自动化搞定
        _MappingKit.mapping(arp);
        me.add(arp);
    }
    
    public static DruidPlugin createDruidPlugin() {
        loadConfig();
        
        return new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password"));
    }
    
    /**
     * 配置全局拦截器
     */
    public void configInterceptor(Interceptors me) {
        
    }
    
    /**
     * 配置处理器
     */
    public void configHandler(Handlers me) {
        
    }
}
package com.demo.index;

import com.jfinal.core.Controller;
import com.jfinal.core.Path;

/**
 * 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
 * 详见 JFinal 俱乐部: https://jfinal.com/club
 * 
 * IndexController
 */
@Path(value = "/", viewPath = "/index")
public class IndexController extends Controller {
    public void index() {
        render("index.html");
    }
}
<fieldset class="solid">
    <legend>新建学生信息</legend>
    <input type="hidden" name="blog.id" value="#(blog.id??)" />
    <div>
        <label>姓名</label>
        <input type="text" name="blog.title" value="#(blog.title??)" />#(titleMsg)
    </div>
     <div>
        <label>班级</label>
        <input type="text" name="blog.content" value="#(blog.content??)"/>  #(contentMsg)
    </div>
    <div>
        <label>&nbsp;</label>
        <input value="提交" type="submit">
    </div>
</fieldset>
#@layout()
#define main()
<h1>学生管理 ---&gt; 新建学生信息
</h1>
<div class="form_box">
    <form action="/blog/save" method="post">
        #include("_form.html")
    </form>
</div>
#end
#@layout()
#define main()
<h1>学生管理系统&nbsp;&nbsp;
<a href="/blog/add">新建学生信息</a>
</h1>
<div class="table_box">
    <table class="list">
        <tbody>
            <tr>
                <th width="4%">id</th>
                <th width="25%">姓名</th>
                <th width="25%">班级</th>
                <th width="12%">操作</th>
            </tr>
            
            #for(x : blogPage.getList())
            <tr>
                <td style="text-align:left;">#(x.id)</td>
                <td style="text-align:left;">#(x.title)</td>
                <td style="text-align:left;">#(x.content)</td>
                <td style="text-align:left;">
                    &nbsp;&nbsp;<a href="/blog/delete/#(x.id)">删除</a>
                    &nbsp;&nbsp;<a href="/blog/edit/#(x.id)">修改</a>
                </td>
            </tr>
            #end
        </tbody>
    </table>
    #@paginate(blogPage.pageNumber, blogPage.totalPage, "/blog/")
</div>
#end
#@layout()
#define main()
<h1>学生管理 ---&gt; 修改学生信息
</h1>
<div class="form_box">
    <form action="/blog/update" method="post">
        #include("_form.html")
    </form>
</div>
#end
#define layout()
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="zh-CN" xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link href="/assets/css/manage.css" media="screen" rel="stylesheet" type="text/css" />
<script src="/assets/js/jquery-1.4.4.min.js" type="text/javascript" ></script>
</head>
<body>
    <div class="manage_container">
        <div class="manage_head">
            <div class="manage_logo">
                <a href="https://jfinal.com" target="_blank">JFinal web framework</a>
            </div>
            <div id="nav">
                <ul>
                    <li><a href="/"><b>首页</b></a></li>
                    <li><a href="/blog"><b>学生管理</b></a></li>
                </ul>
            </div>
        </div>
        <div class="main">
            #@main()
        </div>
    </div>
</body>
</html>
#end
#define paginate(currentPage, totalPage, link)
    #if(totalPage <= 0 || currentPage > totalPage) #return #end
    #setLocal(startPage = currentPage - 4)
    #if (startPage < 1) #setLocal(startPage = 1) #end
    
    #setLocal(endPage = currentPage + 4)
    #if (endPage > totalPage) #setLocal(endPage = totalPage) #end
    
    <div class="pagination">
            #if (currentPage <= 8)
                #setLocal(startPage = 1)
            #end
            #if ((totalPage - currentPage) < 8)
                #setLocal(endPage = totalPage)
            #end
            
            #if (currentPage == 1)
                <span class="disabled prev_page">上页</span>
            #else
                <a href="#(link)#(currentPage - 1)#(append)" class="prev_page">上页</a>
            #end
            
            #if (currentPage > 8)
                <a href="#(link)#(1)#(append)">#(1)</a>
                <a href="#(link)#(2)#(append)">#(2)</a>
                <span class="gap">…</span>
            #end
            
            #for(i : [startPage..endPage])
                #if (currentPage == i)
                    <span class="current">#(i)</span>
                #else
                    <a href="#(link)#(i)#(append)">#(i)</a>
                #end
            #end
            
            #if ((totalPage - currentPage) >= 8)
                <span class="gap">…</span>
                <a href="#(link)#(totalPage - 1)#(append)">#(totalPage - 1)</a>
                <a href="#(link)#(totalPage)#(append)">#(totalPage)</a>
            #end
            
            #if (currentPage == totalPage)
                <span class="disabled next_page">下页</span>
            #else
                <a href="#(link)#(currentPage + 1)#(append)" class="next_page" rel="next">下页</a>
            #end
    </div>
#end
#@layout()
#define main()
<h1>JFinal Demo 项目首页</h1>
<div class="table_box">
    <p>欢迎来到 JFinal极速开发世界!</p>
    
    <br><br><br>
    
    本Demo采用 JFinal Template 作为视图文件。
    点击<a href="/blog"><b>此处</b></a>开始试用Demo。
    
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
</div>
#end

 

posted @ 2022-11-24 21:12  zrswheart  阅读(221)  评论(0编辑  收藏  举报