博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Dubbo、Zookeeper集群搭建及Rose使用心得(二)

Posted on 2015-09-24 14:32  不剃头的一休哥  阅读(1969)  评论(0编辑  收藏  举报

上篇讲了一下配置,这次主要写一下这个框架开发的大概流程。这里以实现 登陆 功能为例。

一、准备工作

  1.访问拦截器  

  用户在进行网站访问的时候,有可能访问到不存在的网页,所以,我们需要把这些链接重新定向到一些存在的网页。比如,我们的页面只有登录页面,但是用户访问了注册页面,这个时候就是不存在的,我们可以把 用户的访问 定向到  自己配置的404页面。具体配置如下(web.xml):

<error-page>
    <error-code>404</error-code>
    <location>/views/404.jsp</location>
</error-page>

   还有一种情况就是 用户访问一些 需要满足某种条件才能访问的页面时,也要对其进行拦截,比如,后台管理中心,要求用户登录才能访问。这个时候就要在java代码中对其进行判断。有两种方式。

  a)通过继承Filter类。这个要现在web.xml中配置,配置代码如下:

<filter>
    <filter-name>exceptionFilter</filter-name>
    <filter-class>com.lhh.myweb.web.controllers.ExceptionFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>exceptionFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

     java代码如下:

package com.lhh.myweb.web.controllers;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ExceptionFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest hsr = (HttpServletRequest) request;
        HttpServletResponse hsrp = (HttpServletResponse) response;
        String uri = hsr.getRequestURI();
        if (!uri.contains("login") && !uri.contains("js") && !uri.contains("css") && !uri.contains("images")
                && !uri.contains("views")) {
            String xrequest = hsr.getHeader("x-requested-with");
            if (xrequest == null) {
                hsrp.sendRedirect(hsr.getContextPath() + "/login");
            } else {
                hsrp.setHeader("r_error_type", "noprivilege");
                hsrp.setHeader("r_exception_msg", "用户没有登录");
                hsrp.setHeader("r_exception_id", "1");
            }
        } else {
            chain.doFilter(request, response);
        }

    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }

}

     从代码中可以看到,这个是对所有的访问进行拦截。和下面要写的方法不同。

    b)继承ControllerInterceptorAdapter类。这个有一个需要注意的地方就是,这段代码要放在controllers文件夹下(Rose框架约定)。代码如下:

package com.lhh.myweb.web.controllers;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.lhh.myweb.common.admin.UserBean;

import net.paoding.rose.web.ControllerInterceptorAdapter;
import net.paoding.rose.web.Invocation;

public class AccessTrackInterceptor extends ControllerInterceptorAdapter {

    @Override
    protected Object before(Invocation inv) throws Exception {
        HttpServletRequest request = inv.getRequest();
        HttpServletResponse response = inv.getResponse();
        HttpSession session = request.getSession();
        UserBean ub = (UserBean) session.getAttribute("user");
        String uri = request.getRequestURI();
        if (ub == null && !uri.contains("login")) {
            String xrequest = request.getHeader("x-requested-with");
            if (xrequest == null) {
                response.sendRedirect(request.getContextPath() + "/login");
            } else {
                response.setHeader("r_error_type", "noprivilege");
                response.setHeader("r_exception_msg", "用户没有登录");
                response.setHeader("r_exception_id", "1");
            }
            return false;
        } else {
            return true;
        }
    }
}

     PS:b和a的区别在于,b在a执行之后才执行,a是对所有的访问链接拦截,b是对注册过的链接拦截。对一个没有注册过的链接访问,比如,http://域名/abc ,这个时候就只有a方法起作用,b方法不起作用。那么何为注册的链接,就是在controllers定义过的。比如如下代码

package com.lhh.myweb.web.controllers;

import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;

@Path("")
public class LoginController {

    @Get("login")
    public String login(){
        return "login";
    }
}

    这里的login就是注册过的链接,如果把login换成abc,那么上面的访问,会先进入a方法再进入b方法。controller的具体用法以后会写到。这里暂且不细说。

   2.上述java代码中可以看到,每个文件夹都有明确的分工。下面就写一下Rose对于文件以及文件夹名称的约定。

    a)控制层。在WEB层中,会对请求进行映射。比如,当用户访问login时,我们返回login的页面。这个是怎么做的呢?首先要创建一个文件夹,名称必须为controllers,如果我们对登陆进行控制,就要在这个文件夹下,新建一个java文件,必须以Controller结尾(注意大小写)比如,LoginController.java。结构如下(代码在方法b中):

    

    解释几个关键字:

     [Get注解是rose框架提供的标识一个http访问是get还是post或者是其他,并且会将path与get中的字符串连接成一个url]   

     下述代码可以从浏览器访问:http://localhost/hello/world [注意path与get中的参数]。

package com.chen.controllers;
import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;

@Path(
"/hello/") public class HelloController {   @Get("world")   public String index() {     return "@hello world";   } }

    返回值也有约定:

      返回普通字符串,如上所述,最常用的做法,返回一个页面。
      以“@”开头的字符串,比如“return "@HelloWorld";”,会将“@”后面的字符串“HelloWorld”作为结果返回;

    b)DAO层。在center层中,对数据库进行访问。这个也对文件命名有约定有,要以DAO结尾。示例代码如下:

package com.yeepay.tctj.center.dao.areautil;

import java.util.Map;

import net.paoding.rose.jade.annotation.DAO;
import net.paoding.rose.jade.annotation.SQL;

@DAO
public interface AreaUtilDAO {
    
    @SQL("select area_id ,area_name from area where area_level = 2")
    public Map<String,String> getAreaCityUtil();
    
    @SQL("select area_id,area_name from area where area_level = 1")
    public Map<String,String> getAreaProvince();
    
}

     具体使用方法以后会提到。这里不多说。

 二、开发流程

  我们要实现的功能是登陆,也就是说用户会输入 用户名 和 密码。

  1.web层代码(LoginController)

package com.lhh.myweb.web.controllers;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;
import net.paoding.rose.web.annotation.rest.Post;

@Path("")
public class LoginController {

    @Get("login")
    public String login(){
        return "login";
    }
    
    @Post("login_check")
    public void login_check(HttpServletRequest request,HttpServletResponse response){
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("username:"+username);
        System.out.println("password:"+password);
    }
}

 

  这段代码的意思是,当用户访问 "login"时,会把login的页面返回过去。当访问,login_check时,会把用户名和密码打印出来。这里需要注意的是,要把"login_check"添加到拦截器中。

  效果如下:

  

  

  2.我们获取到网页传来的值之后开始检查数据库。首先我们在common层定义一个接口。代码如下:

package com.lhh.myweb.common.login;

public interface LoginInterf {

    public String login_check(String username,String password);
}

 

   3.它的实现类在center中。代码如下(LoginImpl):  

package com.lhh.myweb.center.login;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.lhh.myweb.center.dao.LoginDAO;
import com.lhh.myweb.common.admin.UserBean;
import com.lhh.myweb.common.login.LoginInterf;

@Service(value="login")
public class LoginImpl implements LoginInterf{

    @Autowired
    private LoginDAO dao;
    @Override
    public UserBean login_check(String username, String password) {
        // TODO Auto-generated method stub
        UserBean userBean = dao.login_check(username, password);
        return userBean;
    }
}

    注意@Service(value="login")

   LoginDAO代码如下:

package com.lhh.myweb.center.dao;

import com.lhh.myweb.common.admin.UserBean;

import net.paoding.rose.jade.annotation.DAO;
import net.paoding.rose.jade.annotation.SQL;
import net.paoding.rose.jade.annotation.SQLParam;

@DAO
public interface LoginDAO {
    
    @SQL("select name as username,pass as password from user where name = :username and pass = :password")
    public UserBean login_check(@SQLParam("username") String username,@SQLParam("password") String password);
}    

   需要注意的是,LoginInterf是一个服务,要在dubbo-provider.xml注册,代码如下

 <dubbo:service interface="com.lhh.myweb.common.login.LoginInterf" ref="login"/>

  4.在web层再写一个类用于调用这个服务,代码如下(LoginSvc):

package com.lhh.myweb.web.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.lhh.myweb.common.admin.UserBean;
import com.lhh.myweb.common.login.LoginInterf;

@Service
public class LoginSvc {

    @Autowired
    private LoginInterf li;
    public UserBean login_check(String username,String password){
        UserBean ub = li.login_check(username, password);
        return ub;
    };
}

  注意@Service,引入的包是org.springframework.stereotype.Service;

  要在消费者调用 LoginInterf,代码如下:

<dubbo:reference id="login" interface="com.lhh.myweb.common.login.LoginInterf" />

   5.在LoginController中调用LoginSvc.代码如下:

 

package com.lhh.myweb.web.controllers;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;

import com.lhh.myweb.common.admin.UserBean;
import com.lhh.myweb.web.service.LoginSvc;

import net.paoding.rose.web.annotation.Path;
import net.paoding.rose.web.annotation.rest.Get;
import net.paoding.rose.web.annotation.rest.Post;

@Path("")
public class LoginController {

    @Autowired
    private LoginSvc svc;
    @Get("login")
    public String login(){
        return "login";
    }
    
    @Post("login_check")
    public void login_check(HttpServletRequest request,HttpServletResponse response){
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        
        System.out.println("username:"+username);
        System.out.println("password:"+password);
        
        UserBean ub = svc.login_check(username, password);
        
        System.out.println("ubname:"+ub.getUsername());
        System.out.println("ubpass:"+ub.getPassword());
    }
}

 结果如下

 

大致流程就是这样。