未标明原创的文章皆为转载~

使用IKVMC命令编译shiro类库使其在.net环境下可用

java世界有很多优秀的开源类库。如果想在.net世界使用,一种可以手动把java代码转换成C#。如NHibernate,Spring.net,Quartz.net等。但这种方式需要作者同时熟悉java和C#语言,并且要对原项目的架构有所熟悉。所以如果时间精力有限,但又想在.net环境下使用java的优秀类库,可以通过IKVM.NET这个工具把java项目的jar包编译成C#的程序集文件以供使用。本文通过以下步骤讲解shiro这个项目的转换过程。

1,下载最新的IKVM.NET。把zip包解压到某个路径下。如D:\ikvm-7.1.4532.2。

2,在环境变量里的path变量的值里添加:D:\ikvm-7.1.4532.2\bin。(别忘了前面加;号)

3,下载以下jar包:

commons-beanutils-core-1.8.3.jar
commons-logging-api-1.1.1.jar
slf4j-api-1.6.6.jar
slf4j-jdk14-1.6.6.jar
shiro-core-1.2.1.jar
shiro-web-1.2.1.jar

4,在tomcat的lib文件夹下找到以下jar包:

el-api.jar
jsp-api.jar
servlet-api.jar

5,把这些包都放到同一个文件夹下如D:\shiro。

6,因为shiro项目依赖slf4j-api-1.6.6.jar和commons-beanutils-core-1.8.3.jar。而这两个jar包又依赖相应的jar包。经测试,得到如下编译顺序。打开cmd命令行。定位到D:\shiro。输入命令:

ikvmc -target:library commons-logging-api-1.1.1.jar

 

7,如图所示生成:commons-logging-api-1.1.1.dll。

image

 

8,输入命令:

ikvmc -target:library -reference:commons-logging-api-1.1.1.dll commons-beanutils-core-1.8.3.jar

 

9,生成:commons-beanutils-core-1.8.3.dll。

image

10,输入命令(注意是两个jar包):

ikvmc -target:library slf4j-api-1.6.6.jar slf4j-jdk14-1.6.6.jar

11,生成:slf4j-api-1.6.6.dll。

image

12,下面可以生成我们要在.net下使用的程序集了。输入命令:

ikvmc -target:library -reference:slf4j-api-1.6.6.dll -reference:commons-beanutils-core-1.8.3.dll shiro-core-1.2.1.jar

13,生成我们需要的:shiro-core-1.2.1.dll。

image

下面我们在VS2010里建个项目测试下生成的程序集是否可用。就以原shiro项目中的Quickstart例子来测试。

新建控制台应用程序Shiro.Quickstart,添加引用:IKVM.OpenJDK.Core.dll和shiro-core-1.2.1.dll。

添加Shiro.ini和log4j.properties文件,文件属性“复制到输出目录” 都设置为:始终复制。

文件program.cs内容如下:

using System;
using System.Collections.Generic;
using System.Text;

using org.apache.shiro;
using org.apache.shiro.authc;
using org.apache.shiro.config;
using org.apache.shiro.mgt;
using org.apache.shiro.session;
using org.apache.shiro.subject;
using org.apache.shiro.util;
using org.slf4j;
namespace Shiro.Quickstart
{
    class Program
    {
        [NonSerializedAttribute]
        private static readonly Logger log = LoggerFactory.getLogger("Quickstart");
        static void Main(string[] args)
        {
            // The easiest way to create a Shiro SecurityManager with configured
            // realms, users, roles and permissions is to use the simple INI config.
            // We'll do that by using a factory that can ingest a .ini file and
            // return a SecurityManager instance:

            // Use the shiro.ini file at the root of the classpath
            // (file: and url: prefixes load from files and urls respectively):
            Factory factory = new IniSecurityManagerFactory(@"shiro.ini");
            SecurityManager securityManager = (SecurityManager)factory.getInstance();

            // for this simple example quickstart, make the SecurityManager
            // accessible as a JVM singleton.  Most applications wouldn't do this
            // and instead rely on their container configuration or web.xml for
            // webapps.  That is outside the scope of this simple quickstart, so
            // we'll just do the bare minimum so you can continue to get a feel
            // for things.
            SecurityUtils.setSecurityManager(securityManager);

            // Now that a simple Shiro environment is set up, let's see what you can do:

            // get the currently executing user:
            Subject currentUser = SecurityUtils.getSubject();

            // Do some stuff with a Session (no need for a web or EJB container!!!)
            Session session = currentUser.getSession();
            session.setAttribute("someKey", "aValue");
            String value = (String)session.getAttribute("someKey");
            if (value == "aValue")
            {
                log.info("Retrieved the correct value! [" + value + "]");
            }

            // let's login the current user so we can check against roles and permissions:
            if (!currentUser.isAuthenticated())
            {
                UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
                token.setRememberMe(true);
                try
                {
                    currentUser.login(token);
                }
                catch (UnknownAccountException uae)
                {
                    log.info("There is no user with username of " + token.getPrincipal());
                }
                catch (IncorrectCredentialsException ice)
                {
                    log.info("Password for account " + token.getPrincipal() + " was incorrect!");
                }
                catch (LockedAccountException lae)
                {
                    log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                            "Please contact your administrator to unlock it.");
                }
                // ... catch more exceptions here (maybe custom ones specific to your application?
                catch (AuthenticationException ae)
                {
                    //unexpected condition?  error?
                }
            }

            //say who they are:
            //print their identifying principal (in this case, a username):
            log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

            //test a role:
            if (currentUser.hasRole("schwartz"))
            {
                log.info("May the Schwartz be with you!");
            }
            else
            {
                log.info("Hello, mere mortal.");
            }

            //test a typed permission (not instance-level)
            if (currentUser.isPermitted("lightsaber:weild"))
            {
                log.info("You may use a lightsaber ring.  Use it wisely.");
            }
            else
            {
                log.info("Sorry, lightsaber rings are for schwartz masters only.");
            }

            //a (very powerful) Instance Level permission:
            if (currentUser.isPermitted("winnebago:drive:eagle5"))
            {
                log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                        "Here are the keys - have fun!");
            }
            else
            {
                log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
            }

            //all done - log out!
            currentUser.logout();
            System.Console.ReadKey();
        }
    }
}

 

按F5调试。运行成功。说明程序集基本可用。

image

结语:

但是,也应注意到debug下生成的所有文件达25M。而且在正式商用项目中性能也可能是一个问题。

这个只有自己在实际使用中权衡利弊了。

posted @ 2012-08-14 23:24 CodeYu 阅读(...) 评论(...) 编辑 收藏