图书管理系统【用户、购买、订单模块、添加权限】(三)

简介: 笔记

生成订单的Servlet


BussinessServiceImplservice=newBussinessServiceImpl();


       //检查该用户的购物车是否有商品

       Cartcart=(Cart)request.getSession().getAttribute("cart");

       if(cart==null){

           request.setAttribute("message","您购物车没有商品,无法生成订单");

           request.getRequestDispatcher("/message.jsp").forward(request,response);

           return;

       }


       //如果有商品,得到当前用户

       Useruser=(User)request.getSession().getAttribute("user");

       service.createOrder(cart,user);

       request.setAttribute("message","订单已经生成了,准备好钱来收货把");

       request.getRequestDispatcher("/message.jsp").forward(request,response);

       return;


用户查询自己的订单Servlet


<ahref="${pageContext.request.contextPath}/LookOrder"target="body">查看订单</a>

BussinessServiceImplservice=newBussinessServiceImpl();


       //检查该用户是否登陆了

       Useruser=(User)request.getSession().getAttribute("user");

       if(user==null){

           request.setAttribute("message","您还没登陆,等您登陆了再来看把");

           request.getRequestDispatcher("/message.jsp").forward(request,response);

           return;

       }


       //用户登陆了!

       Orderorder=service.findUserOrder(user.getId());


       //交给相对应的JSP 显示

       request.setAttribute("order",order);

       request.setAttribute("user",user);

       request.getRequestDispatcher("/client/listOrder.jsp").forward(request,response);

       return;


显示订单数据的JSP


<c:iftest="${order==null}">

   您还没有下过任何订单!!


</c:if>


<c:iftest="${order!=null}">


   <tableborder="1px">


       <tr>

           <td>下单人:</td>

           <td>订单时间</td>

           <td>订单状态</td>

           <td>订单价钱</td>

       </tr>

       <tr>

           <td>${user.username}</td>

           <td>${order.ordertime}</td>

           <td>${order.state==false?"未发货":"已发货"}</td>

           <td>${order.price}</td>

       </tr>


   </table>


</c:if>



后台查询订单的状况Servlet


<ahref="${pageContext.request.contextPath}/OrderServlet?state=false"target="body">待处理订单</a><br>

<ahref="${pageContext.request.contextPath}/OrderServlet?state=true"target="body">已发货订单</a><br>

BussinessServiceImplservice=newBussinessServiceImpl();

       Stringstate=request.getParameter("state");


       if(state.equals("true")){

           List<Order>list=service.getAllOrder(true);

           request.setAttribute("list",list);


       }elseif(state.equals("false")){

           List<Order>list=service.getAllOrder(false);

           request.setAttribute("list",list);

       }



       request.getRequestDispatcher("/background/listOrder.jsp").forward(request,response);


显示订单状况的JSP


<c:iftest="${empty(list)}">


   还没有任何订单哦!


</c:if>


<c:iftest="${!empty(list)}">


   <tableborder="1px">


       <tr>

           <td>下单人:</td>

           <td>订单时间</td>

           <td>订单状态</td>

           <td>订单价钱</td>

           <td>操作</td>

       </tr>


       <c:forEachitems="${list}"var="order">

           <tr>

               <td>${order.user_id}</td>

               <td>${order.ordertime}</td>

               <td>${order.state==false?"未发货":"已发货"}</td>

               <td>${order.price}</td>

               <td>

                   <ahref="${pageContext.request.contextPath}/orderItemServlet?order_id=${order.id}">查看详细信息</a>

                   <ahref="#">删除</a>


               </td>

           </tr>

       </c:forEach>



   </table>



</c:if>


查看具体订单的详细信息Servlet


BussinessServiceImplservice=newBussinessServiceImpl();


       //得到用户想要查看详细信息的表单

       Stringorder_id=request.getParameter("order_id");


       Orderorder=service.findOrder(order_id);


       //将该order对象给相对应的JSP显示

       request.setAttribute("order",order);

       request.getRequestDispatcher("/background/listDetail.jsp").forward(request,response);


查看具体订单的详细信息JSP


<tableborder="1px">


  <tr>

      <td>书籍的编号</td>

      <td>价钱</td>

      <td>数量</td>

      <td>操作</td>

  </tr>

   <c:forEachitems="${order.items}"var="item">

       <tr>

           <td>${item.book_id}</td>

           <td>${item.price}</td>

           <td>${item.quantity}</td>

           <td><ahref="${pageContext.request.contextPath}/SendOutServlet?id=${order.id}">发货</a></td>

       </tr>

   </c:forEach>

</table>


处理发货的Servlet


BussinessServiceImplservice=newBussinessServiceImpl();

       Stringid=request.getParameter("id");


       service.sendOutOrder(id);

       request.setAttribute("message","已发货!");

       request.getRequestDispatcher("/message.jsp").forward(request,response);

       return;



添加权限控制


目前为止,我们已经学习了动态代理技术和注解技术了。于是我们想要为之前的bookStore项目添加权限控制.....

只有用户有权限的时候,后台管理才可以进行相对应的操作.....


实现思路

46.jpg

之前我们做权限管理系统的时候,是根据用户请求的URI来判断该链接是否需要权限的。这次我们使用动态代理的技术和注解来判断:用户调用该方法时,检查该方法是否需要权限...

根据MVC模式,我们在web层都是调用service层来实现功能的。那么我们具体的思路是这样的:

  • web层调用service层的时候,得到的并不是ServiceDao对象,而是我们的代理对象
  • 在service层中的方法添加注解,如果方法上有注解,那么说明调用该方法需要权限...
  • 当web层调用代理对象方法的时候,代理对象会判断该方法是否需要权限,再给出相对应的提示....


设计实体、数据库表


上次我们做的权限管理系统是引入了角色这个概念的,这次主要为了练习动态代理和注解技术,就以简单为主,不引入角色这个实体。直接是用户和权限之间的关系了。


Privilege实体


publicclassPrivilege{


   privateStringid;

   privateStringname;


   publicStringgetId(){

       returnid;

   }


   publicvoidsetId(Stringid){

       this.id=id;

   }


   publicStringgetName(){

       returnname;

   }


   publicvoidsetName(Stringname){

       this.name=name;

   }

}


数据库表


  • privilege表

CREATETABLEprivilege(


 id   VARCHAR(40)PRIMARYKEY,

 nameVARCHAR(40)


);

privilege和user是多对多的关系,于是使用第三方表来维护他们的关系

  • user_privilege表

CREATETABLEuser_privilege(

 privilege_idVARCHAR(40),

 user_id      VARCHAR(40),


 PRIMARYKEY(privilege_id,user_id),

 CONSTRAINTprivilege_id_FKFOREIGNKEY(privilege_id)REFERENCESprivilege(id),

 CONSTRAINTuser_id_FK1FOREIGNKEY(user_id)REFERENCESuser(id)


);



添加测试数据


为了方便,直接添加数据了。就不写详细的DAO了。

  • 在数据库中添加了两个权限

48.jpg

为id为1的user添加了两个权限

49.jpg


编写DAO


后面在动态代理中,我们需要检查该用户是否有权限...那么就必须查找出该用户拥有的哪些权限。再看看用户有没有相对应的权限

//查找用户的所有权限

   publicList<Privilege>findUserPrivilege(Stringuser_id){

       QueryRunnerqueryRunner=newQueryRunner(Utils2DB.getDataSource());


       Stringsql="SELECT p.* FROM privilege p, user_privilege up WHERE p.id = up.privilege_id AND up.user_id = ?";

       try{

           return(List<Privilege>)queryRunner.query(sql,newObject[]{user_id},newBeanListHandler(Privilege.class));

       }catch(SQLExceptione){

           thrownewRuntimeException(e);

       }

   }


抽取到接口上


List<Privilege>findUserPrivilege(Stringuser_id);



注解模块


  • 编写注解

@Retention(RetentionPolicy.RUNTIME)

public@interfacepermission{

   Stringvalue();

}

  • 在Service层方法中需要权限的地方添加注解CategoryServiceImpl

@permission("添加分类")

   /*添加分类*/

   publicvoidaddCategory(Categorycategory){

       categoryDao.addCategory(category);

   }



   /*查找分类*/

   publicvoidfindCategory(Stringid){

       categoryDao.findCategory(id);

   }


   @permission("查找分类")

   /*查看分类*/

   publicList<Category>getAllCategory(){

       returncategoryDao.getAllCategory();

   }


抽取Service


把Service的方法抽取成ServiceDao。在Servlet中,也是通过ServiceFactory来得到Service的对象【和DaoFactory是类似的】


CategoryService


@permission("添加分类")

   /*添加分类*/voidaddCategory(Categorycategory);


   /*查找分类*/

   voidfindCategory(Stringid);


   @permission("查找分类")

   /*查看分类*/List<Category>getAllCategory();


ServiceFactory


publicclassServiceDaoFactory{


   privatestaticfinalServiceDaoFactoryfactory=newServiceDaoFactory();


   privateServiceDaoFactory(){

   }


   publicstaticServiceDaoFactorygetInstance(){

       returnfactory;

   }



   //需要判断该用户是否有权限

   public<T>TcreateDao(StringclassName,Class<T>clazz,finalUseruser){


       System.out.println("添加分类进来了!");


       try{

           //得到该类的类型

           finalTt=(T)Class.forName(className).newInstance();

           //返回一个动态代理对象出去

           return(T)Proxy.newProxyInstance(ServiceDaoFactory.class.getClassLoader(),t.getClass().getInterfaces(),newInvocationHandler(){


               @Override

               publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsNoSuchMethodException,InvocationTargetException,IllegalAccessException,PrivilegeException{

                   //判断用户调用的是什么方法

                   StringmethodName=method.getName();

                   System.out.println(methodName);


                   //得到用户调用的真实方法,注意参数!!!

                   Methodmethod1=t.getClass().getMethod(methodName,method.getParameterTypes());


                   //查看方法上有没有注解

                   permissionpermis=method1.getAnnotation(permission.class);


                   //如果注解为空,那么表示该方法并不需要权限,直接调用方法即可

                   if(permis==null){

                       returnmethod.invoke(t,args);

                   }


                   //如果注解不为空,得到注解上的权限

                   Stringprivilege=permis.value();


                   //设置权限【后面通过它来判断用户的权限有没有自己】

                   Privilegep=newPrivilege();

                   p.setName(privilege);


                   //到这里的时候,已经是需要权限了,那么判断用户是否登陆了

                   if(user==null){


                       //这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。

                       thrownewPrivilegeException("对不起请先登陆");

                   }


                   //执行到这里用户已经登陆了,判断用户有没有权限

                   Methodm=t.getClass().getMethod("findUserPrivilege",String.class);

                   List<Privilege>list=(List<Privilege>)m.invoke(t,user.getId());


                   //看下权限集合中有没有包含方法需要的权限。使用contains方法,在Privilege对象中需要重写hashCode和equals()

                   if(!list.contains(p)){

                       //这里抛出的异常是代理对象抛出的,sun公司会自动转换成运行期异常抛出,于是在Servlet上我们根据getCause()来判断是不是该异常,从而做出相对应的提示。

                       thrownewPrivilegeException("您没有权限,请联系管理员!");

                   }


                   //执行到这里的时候,已经有权限了,所以可以放行了

                   returnmethod.invoke(t,args);

               }

           });


       }catch(Exceptione){

           newRuntimeException(e);

       }

       returnnull;

   }

}


PrivilegeExcetption


当用户没有登陆或者没有权限的时候,我们应该给用户一些友好的提示....于是我们自定义了PrivilegeException

publicclassPrivilegeExceptionextendsException{


   publicPrivilegeException(){

       super();

   }


   publicPrivilegeException(Stringmessage){

       super(message);

   }


   publicPrivilegeException(Stringmessage,Throwablecause){

       super(message,cause);

   }


   publicPrivilegeException(Throwablecause){

       super(cause);

   }

}

我们继承的是Exception,通过方法名抛出去。但是我们是通过代理对象调用方法的,于是sun公司的策略就是把它们转换成运行期异常抛出去

因此,我们就在Servlet上得到异常,再给出友好的提示。。


效果:


  • 没有登陆的时候:

49.gif

  • 登陆了,但是没有相对应的权限的时候
  • 登陆了,并且有权限

50.gif


要点总结


该权限控制是十分优雅的,只要我在Service层中添加一个注解...那么当web层调用该方法的时候就需要判断用户有没有该权限....

  1. 外界调用Service层的方法是代理调用invoke()方法,我们在invoke()方法可以对其进行增强!
  2. invoke()方法内部就是在查询调用该方法上有没有注解,如果没有注解,就可以直接调用。如果有注解,那么就得到注解的信息,判断该用户有没有权限来访问这个方法
  3. 在反射具体方法的时候,必须记得要给出相对应的参数!
  4. 在invoke()方法抛出的编译时期异常,java会自动转换成运行期异常进行抛出...
  5. 使用contains()方法时,就要重写该对象的hashCode()和equals()


目录
相关文章
|
3月前
|
API 开发工具
支付系统23-------使用沙箱账号进行支付测试,统一收单并支付页面接口的调用
支付系统23-------使用沙箱账号进行支付测试,统一收单并支付页面接口的调用
|
数据安全/隐私保护
阿里云国际版账户简便注册流程
如需注册阿里云国际版账号,可以与alicloudlx联系,只需要一个邮箱就ok了,简单快捷
阿里云国际版账户简便注册流程
|
数据安全/隐私保护
4-企业权限管理-订单操作
4-企业权限管理-订单操作
4-企业权限管理-订单操作
|
消息中间件 数据库 RocketMQ
创建支付订单流程|学习笔记
快速学习创建支付订单流程
340 0
创建支付订单流程|学习笔记
|
开发者 微服务
课程支付功能(生成订单接口2) | 学习笔记
简介:快速学习课程支付功能(生成订单接口2)
课程支付功能(生成订单接口2) | 学习笔记
|
XML JSON Java
课程支付功能(生成订单接口1) | 学习笔记
简介:快速学习课程支付功能(生成订单接口1)
174 0
课程支付功能(生成订单接口1) | 学习笔记
|
XML API 数据格式
课程支付功能(查询订单接口) | 学习笔记
简介:快速学习课程支付功能(查询订单接口)
|
XML Java 网络安全
纳税服务系统一(用户模块)【简单增删改查、日期组件、上传和修改头像】(一)
为了更好地掌握SSH的用法,使用一个纳税服务系统来练手…..搭建SSH框架环境在上一篇已经详细地说明了。
117 0
纳税服务系统一(用户模块)【简单增删改查、日期组件、上传和修改头像】(一)
|
Java 网络安全
纳税服务系统一(用户模块)【简单增删改查、日期组件、上传和修改头像】(二)
为了更好地掌握SSH的用法,使用一个纳税服务系统来练手…..搭建SSH框架环境在上一篇已经详细地说明了。
160 0
纳税服务系统一(用户模块)【简单增删改查、日期组件、上传和修改头像】(二)
|
JavaScript Java 网络安全
纳税服务系统一(用户模块)【简单增删改查、日期组件、上传和修改头像】(三)
为了更好地掌握SSH的用法,使用一个纳税服务系统来练手…..搭建SSH框架环境在上一篇已经详细地说明了。
179 0
纳税服务系统一(用户模块)【简单增删改查、日期组件、上传和修改头像】(三)