上篇讲了一下配置,这次主要写一下这个框架开发的大概流程。这里以实现 登陆 功能为例。
一、准备工作
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());
}
}
结果如下
大致流程就是这样。