jfinal 小例子 (一)

本文详细介绍了一个基于JFinal框架的后台登录模块实现过程,包括路由设置、控制器编写、验证码生成、用户验证等功能。

假如我们需要做个后台管理模块,我们来模拟下登陆过程

1、创建工程,准备好jar包,我使用的是mysql(这里提一句,mysql-jdbc的jar包官网下载是msi文件,解压就行了)

主要的jar包有下面这些:

164626_ihKd_218357.png

2、创建工程,项目分为前台门户,和后台管理,webroot 下建 MenHu和HouTai两个文件夹,也可以把脚本,样式的文件夹都建好

如下图:

164955_KHx3_218357.png


3、我们暂时只关注HouTai这一块

1)我们要的是什么

(一)、访问 localhost:8080/Programs/HouTai/时,进入后台登陆页面login.html

(二)、访问 .../HouTai/main(主页面)时,判断用户是否登陆了,如果没有登陆,那么进入login.html,如果登陆了就到main.html

(三)、登陆过程我们需要验证输入账号密码格式,成功后在验证密码是否正确。最后进入main.html


    针对第一步,我们建数据表,添加几条数据进去,要有个用户表users,有id,name,password,phone几个字段就好了,这里我们使用phone 来做账号。


2)创建路由类baseRoute,三个控制器类IndexController和HouTaiController、CommonController(暂时控制了登陆和验证码)

baseRoute:

/**
 * 内容摘要 :
 *
 * 类修改者	修改日期
 * 这个基础路由,将门户网站和后台管理模块分开,分别由IndexController
 * 和HouTaiController来控制页面路径。其他的action 的控制另外配置
 * @ClassName IndexRoute
 * <p>Company: knowology </p>
 * @author c_wolf your emai address
 * @date 2014-7-2 下午12:32:34
 * @version V1.0
 */

public class baseRoute extends Routes{
	@Override
	public void config() {
		//门户前端控制
		add("/", IndexController.class,"/MenHu");
		//后台管理模块控制
		add("/HouTai",HouTaiController.class,"/HouTai");
		//某些公共资源,例如验证码
		add("Common",CommonController.class);
		
	}
	

}


IndexC....:

public class IndexController extends Controller{
	public void index(){
		
		/**
		 * 一些逻辑,一些数据
		 */
		render("index.html");
	}
	
	public void about(){
		render("about.html");
	}
	
	public void product(){
		render("product.html");
	}
}

HouTai...:

public class HouTaiController extends Controller {
	//默认页面为登陆页面
	public void index(){
		render("login.html");
	}
	
	
	//跳转到后台管理页面主页面,默认先加载当前用户能操作的业务
	public void main(){
		User user = (User)getSessionAttr("user");
		String id = user.get("id").toString();
		String sql = "SELECT s.name,s.url,s.id FROM rel_user_service rel,service s WHERE rel.serviceid=s.id AND rel.userid=?";
		List<Service> services = Service.dao.find(sql, id);
		setAttr("services", services);		
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		render("main.html");
	}
	

}


common..:

public class CommonController extends Controller {
	public static final String KEY= "mykey";
	@SuppressWarnings("rawtypes")
	public Map responseM = new HashMap();//用来存放返回的数据(json)
	//生成验证码
	public void imgcode() {
                //这个是jfinal自带的验证码生成类,可以直接使用的
		CaptchaRender img = new CaptchaRender(KEY);

		render(img);
	}
	
	
	@SuppressWarnings("unchecked")
	@Before({LoginFormat.class,LoginPwd.class})//先进行格式验证,在验证密码正确性
	
	//登陆action
	public void login(){
		//经过前面的验证,已经确定用户登录成功。
		//查询用户基本信息,放入session(基本信息主要为,用户名,角色,id等,具体看个人的情况,想放什么就放什么)
		String sql = "select id,username,phone from users where phone=? limit 1";
		User user = User.dao.findFirst(sql, getPara("phone"));
		setSessionAttr("user", user);
		responseM.put("state", "success");
		//返回成功登录的标志
		renderJson(responseM);
	}



DemoConfig:

@Override
	public void configRoute(Routes me) {
		me.add(new baseRoute());//加入我们的路由
	}



通过这几个类,可以看出访问 /HouTai/main时,没有经过验证就进入了main.html。我们加一个handler 类,来控制下

public class BaseHandler extends Handler {
	@Override
	public void handle(String target, HttpServletRequest request,
			HttpServletResponse response, boolean[] isHandled) {
		
		//如果路径中包含HouTai(该路径下所有资源),那么验证身份,通过验证才能进入后台管理模块
		if(target.indexOf("HouTai")>0){
			HttpSession session = request.getSession(false);
			if(session==null||session.getAttribute("user")==null){				
			//验证不成功,跳转到后台登陆页面
				target="/HouTai/index";
			}
		}
		nextHandler.handle(target, request, response, isHandled);
	}


好了,这下用户进不去main.html了。我们来看下登陆页面

login.html:(登陆页面使用jquery 来异步验证登陆,成功后跳转页面,失败后,给提示)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>login.html</title>
<base href="/项目名/"><!--这里加上base个人觉得是有好处的,让页面引用资源全部基于项目根路径,不容易出错 -->
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script src="Scripts/jquery-1.9.1.min.js"></script>

<link rel="shortcut icon" href="Images/favicon.ico" />
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
<script type="text/javascript">
	$(function() {
		$("#login_btn").removeAttr("disabled");
		/**
		 *1、input绑定回车
		 */
		$("#login_form input").bind("keyup", function(e) {
			var ev = document.all ? window.event : e;
			if (ev.keyCode == 13) {//如果是回车,那么提交表单
				submitForm();
			}
		});
	});

	/**
	 提交表单
	 */
	function submitForm() {
		//清空所有错误提示
		$(".msg").html("");
		$("#login_btn").attr("disabled","disabled");
		$.post("Common/login", $("#login_form").serialize(), function(data) {
			$("#login_btn").removeAttr("disabled");
			var responseM = data;
			if(responseM.state=='error'){//登陆不成功,显示所有的错误提示
				for(var key in responseM){
					if(key!='error')
					$("#"+key).html(responseM[key]);
				}
			}else{//登陆成功,跳转页面
			location = "HouTai/main";
			}
		}, "json");
	}
</script>
<style>
.msg{
color:red;
font-size:0.8em;
}
</style>

<body>
<!--这里说明下,form表单中,input 的name要和后面错误提示的id想对应,这样程序写起来会更方便 -->
	<form id="login_form" method="post" action="Common/login">
		电话:<input name='phone' /><span class='msg' id="phoneMsg"></span><br> <br> 
		密码:<input
			name='password' type="password" /><span class='msg' id="passwordMsg"></span> <br> <br>
		验证:<input name="imgcode" /><span class='msg' id='imgcodeMsg'></span><br> <br> <img
			src="Common/imgcode"
			onclick="this.src='Common/imgcode?'+Math.random()" /> <input
			id="login_btn" onclick="submitForm()" type="button" value="登陆">
	</form>

</body>
</html>


效果将会是这样的:

171944_Pyo1_218357.png

171944_ngqy_218357.png


3)后台需要验证数据的格式,jfinal 中有validator。我们也建一个

public class LoginFormat extends Validator{
	@SuppressWarnings("rawtypes")
	public Map responseM = new HashMap();//用来存放返回的数据(json)
			//进行phone
			static String regPhone = "^1[1-9]{10}$";
			//进行密码验证正则,6-15位数字和字母特殊字符的组合
			static String regPassword="^[A-Za-z0-9(!@#$%&)]{6,15}$";
			//验证码格式
			static String regImgcode = "^[A-Za-z0-9(!@#$%&)]{6}";
	
	@Override
	protected void validate(Controller c) {
		//验证账号和密码
		validateRegex("phone", regPhone, "phoneMsg", "电话号码格式不正确!");
		validateRegex("password", regPassword, "passwordMsg", "密码格式为6-15为英文与数字结合!");
		validateRegex("imgcode", regImgcode, "imgcodeMsg", "验证码格式不正确!");
		
		
	}

	
	@SuppressWarnings("unchecked")
	@Override
	protected void handleError(Controller c) {
		Enumeration<String>  en =c.getParaNames();
		while (en.hasMoreElements()) {
			//错误键,我们规定,所有的错误为 请求字段加上 Msg 
			String key = en.nextElement().toString()+"Msg";
			if(c.getAttrForStr(key)!=null){
				responseM.put(key, c.getAttrForStr(key));
			}
			
        }
        //这样我们可以将所有的错误作为一个json串返回前端页面
		responseM.put("state", "error");
		c.renderJson(responseM);
		
	}


同时我们需要在之前的CommonController 的login方法上面加上 注解,在login 方法执行前,去验证数据格式

@Before(LoginFormat.class)


验证完格式后,我们还需要验证数据是否正确(验证码正确,密码正确),这时候需要用到数据库了,配置下:

@Override
	public void configPlugin(Plugins me) {
				//先加载配置文件,源码显示,加载的是web-inf下的文件,所以配置文件放在web-inf文件夹下
				loadPropertyFile("jdbc.properties");
				//getProperty 
				C3p0Plugin cp = new C3p0Plugin(getProperty("jdbcurl"),
				"root", "root");
				me.add(cp);
				ActiveRecordPlugin arp = new ActiveRecordPlugin(cp);
				me.add(arp);
				arp.addMapping("users", User.class);
				arp.addMapping("service", Service.class);
				me.add(new EhCachePlugin());
				
				
		
	}


验证数据的正确性,我们也创建个validator 来做,代码几乎类似(不要忘了login 方法加注解)

public class LoginPwd extends Validator {
	private Map<String, String> responseM = new HashMap<String, String>();
	
	@Override
	protected void validate(Controller c) {
		//验证码忽略大小写,这里用到了jfinal 自带的验证验证码的方法
		boolean b = CaptchaRender.validate(c, c.getPara("imgcode").toUpperCase(), CommonController.KEY);
		if(!b){
			addError("imgcodeMsg", "验证码不正确!");
			return;
		}		
		//验证码正确,验证密码
		String phone = c.getPara("phone");
		//MD5加密后与数据库数据进行比较
		String password = StringUtil.encodePassword(c.getPara("password"), "MD5");
		String sql = "select password from users where phone =? limit 1";
		User user = User.dao.findFirst(sql, phone);
		
		if(!password.equals(user.get("password").toString())){
			addError("passwordMsg", "密码不正确!");
			return;
		}
		
		
		
	}

	
	@Override
	protected void handleError(Controller c) {
		Enumeration<String>  en =c.getParaNames();
		while (en.hasMoreElements()) {
			//错误键,我们规定,所有的错误为 请求字段加上 Msg 
			String key = en.nextElement().toString()+"Msg";
			if(c.getAttrForStr(key)!=null){
				responseM.put(key, c.getAttrForStr(key));
			}
			
        }
		responseM.put("state", "error");
		c.renderJson(responseM);
	}
	
}


页面效果如下:

173226_Skd0_218357.png

173226_kbEi_218357.png


4)登陆成功后进入mian.html(我用了esayui,jquery,稍微加了几个div)

main.html:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>main.html</title>
<base href="/Pro/">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<link rel="shortcut icon" href="Images/favicon.ico" />
<script src="Scripts/jquery-1.9.1.min.js"></script>
<link rel="stylesheet" type="text/css"
	href="Scripts/jquery-easyui-1.3.6/themes/icon.css">
<script type="text/javascript" src="Scripts/jquery.cookie.js"></script>
<script type="text/javascript" src="HouTai/HTScripts/common.js"></script>
<link type="text/css" rel="stylesheet" href="Styles/common.css" />
<body>

	<div id="cc" class="easyui-layout" style="height:600;overflow:hidden;">  
    <div data-options="region:'north'" style="height:60px;border:none;background:url(Images/ht_bg.png)">
    
    <div class="ht_top" style="folat:left;">
    	<div id='ht_logo_text'>
    		 卖包子后台管理系统
    	</div>
    	
    	<div style="float:right;color:white;margin-right:20px;">
    		<!-- 如果session 存在,那么就显示登陆成功,否则,跳转回到登陆页面 -->
		<#if session??> 欢迎您:${session["user"]["username"]} <#else>
		<script>
			location = HouTai / index;
		</script>
		</#if>
		<br>
		 <input name='n1' type="radio" onclick="changeTheme('default')">default
		  <input name='n1' type="radio" onclick="changeTheme('gray')">gray
		   <input name='n1' type="radio" onclick="changeTheme('bootstrap')">bootstrap
		    <input name='n1' type="radio" onclick="changeTheme('black')">black
		     <input name='n1' type="radio" onclick="changeTheme('metro')">metro
		
		</div>
    	
	</div>
    
    </div>  
    <div data-options="region:'center'" style="height:100px;">
    <div class="easyui-tabs" style="height:450px">
		<#list services as service>
		<div title='${service["name"]}' style="padding:10px"></div>
		</#list>
	</div>
    
    </div>  
	</div>
		<br>
	
</body>
<script src="Scripts/jquery-easyui-1.3.6/jquery.easyui.min.js"></script>
</html>

最后显示效果为:(显示出当前欢迎你:登录人)

173548_lpTq_218357.png



5)我的login方法中加了个sleep(500),模拟下后台加载很多数据。使用firebug 看到 main请求花了 505毫秒

我们给它加上缓存

缓存这个东西不是所有的方法都要加,看情况,例如一些大家都能用到的公共数据(门户首页数据)可以放缓存,让别人不用再加载了,私人数据直接放session就行了(类似私人缓存吧)

在login 方法上加上注解:

@Before(CacheInterceptor.class)


最后看下效果,main请求第二次加载只需要10毫秒


结束:这个小例子就到这里结束








































转载于:https://my.oschina.net/daluobo/blog/287025

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值