sitebricks 学习笔记之用户登录和ajax form

这次是一个简单的登录界面,前台由jquery.form负责判断输入是否非空以及无刷新显示后台登录信息。就这么简单,但是中间还是碰到了一个问题,困扰了很久。

先来看看我最初的代码:

一、数据库查询

用的是guice-persist的DynamicFinder,所以只需要实现一个接口,而不需要具体实现。配置方法见本人前面的文章《sitebricks 学习笔记之guice-persist的配置和使用

UserFinder.java:

public interface UserFinder {

    @Finder(query = "select u from User u where u.name=:name and u.password=:password")
    User authenticated(@Named("name") String name, @Named("password") String password);

}

 二、前台登录界面:

使用了sitebricks的decoration技术,详细方法见《sitebricks学习笔记之decoration》。

Login.java:

@Decorated
public class Login extends Decorator {
    public Login() {
    }

    @Override
    public String getPageTitle(){
        return "Bricks - 用户登录";
    }
}

 Login.html:

<!DOCTYPE HTML>
<html>
<head>
    <title>none</title>
    @Require
    <script type="text/javascript" charset="UTF-8" src="static/js/jquery-1.7.2.min.js"></script>
    @Require
    <script type="text/javascript" charset="UTF-8" src="static/js/jquery.form.js"></script>
</head>
<body>
<script type="text/javascript">
    $(document).ready(function()
            {
                $('#loginform').submit(function()//提交表单
                {
                    var options = {
                        target:'#msg',
                        url:'/hello', //提交给哪个执行
                        type:'POST',
                        beforeSubmit: validate,
                        success: function(data){ $('#msg').html(data.info);} //显示操作提示
                    };
                    $('#loginform').ajaxSubmit(options);
                    return false; //为了不刷新页面,返回false,反正都已经在后台执行完了,没事!
                });
            }
    );
    function validate(formData, jqForm, options) {
        for (var i=0; i < formData.length; i++) {
            if (!formData[i].value) {
                $('#msg').html('请输入用户名和密码!');
                return false;
            }
        }
    }
</script>
<div class="login_container" id="login">
    <div id="msg"></div>
    <div class="login_box">
        <div class="logo_title">
            <h1><img src="/static/images/login_title.gif"/>用户登录</h1>
        </div>
        <div class="login_operate">
            <form id="loginform" method="post" name="loginform">
                <div class="username">
                    <label class="txt_default" for="name">用户名</label>
                    <input class="txt alias" id="name" name="name" type="text" tabindex="1"/>
                </div>
                <div class="password">
                    <label class="txt_default" for="password">密&nbsp;&nbsp;&nbsp;码</label>
                    <input class="txt password" id="password" name="password" type="password" tabindex="2"/>
                </div>
                <div class="about_password">
                    <input class="remerber_password" id="remerber_password" type="checkbox" disabled/>
                    <label for="remerber_password">记住登录状态</label>
                    <a class="forgetPassword" href="" target="_blank">忘记密码?</a>
                </div>
                <div class="login_submit">
                    <a class="login_btn_wrapper" href=""><input class="login_btn" type="submit" value="登录"/></a>
                </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>

 这里注意两点:1、由于使用了decoration,所以引入的两个必需的js文件,必须使用@Require,不然的话在最终输出的页面中将不会出现这两个js文件。

2、ajax form的具体执行代码需要放在<body>内,原因同上。

三、后台处理

Hello.java:

public class Hello {
    @Inject
    private UserFinder finder;

    private String name;
    private String password;

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Post
    public Reply<Map<String, String>> hello() {
       User user = finder.authenticated(name, password);
        Map<String, String> result = new HashMap<String, String>();
        if (user!=null)
            result.put("info", "用户" + name + "登录成功!");
        else result.put("info", "用户名或密码错误!");
        return Reply.with(result).as(Json.class);
    }
}

 这里注意不要忘了name和password的getter/setter。

四、运行时问题出现

当数据库中不存在所查询的对象时,将会抛出NoResultException。

五、解决办法:

方案一:最初的时候,我用的办法是自己写一个Dao,在获取结果时使用try-catch,当jpa返回NoResultException时,使user=null。

UserDao.java:

public class UserDao{
    @Inject 
    private EntityManager em;

    public User authencated(String name, String password){
         Query q = em.createQuery("select u from User where u.name=:name and u.password=:password");
         User user = null;
         try{
                 user = (User) q.getSingleResult();
                 return user;
         }catch(NoResultException e){
                  return null;
         }
         finally{return user;}
    }
}
 然后将Hello.java中的
private UserFinder finder;

 改为

private UserDao finder;

 其他代码不变,运行正常。但是总觉得这样风格太不统一,就像是一个hack。于是google了一下,发现guice-persist的这个问题与warp-persist是一脉相承的,出现NoresultException其实不是@Finder的问题,而是jpa规范的要求。那么,就没有解决办法了吗?warp-persist&sitebricks的作者dhanji告诉了我们解决方案。

方案二:

很简单,只需要修改@Finder的返回类型为ArrayList<User>,然后在Hello.java修改一下判断语句即可。

UserFinder.java:

public interface UserFinder {

    @Finder(namedQuery = "getUserByNamePwd", returnAs = ArrayList.class)
    ArrayList<User> authenticated(@Named("name") String name, @Named("password") String password);

}

 注意,@Finder里必须指明returnAs。

Hello.java:

public class Hello {
    @Inject
    private UserFinder finder;

    private String name;
    private String password;

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Post
    public Reply<Map<String, String>> hello() {
       ArrayList<User> users = finder.authenticated(name, password);
        System.out.println("\n>>>[BRICKS] Hello world!");
        Map<String, String> result = new HashMap<String, String>();
        if (!users.isEmpty())
            result.put("info", "用户" + name + "登录成功!");
        else result.put("info", "用户名或密码错误!");
        return Reply.with(result).as(Json.class);
    }
}
 这样,即使结果集为空,运行时也不会抛出异常了。

你可能感兴趣的:(jquery,登录,sitebricks,guice-persist)