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