使用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。而且在正式商用项目中性能也可能是一个问题。

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

你可能感兴趣的:(shiro)