文档章节

maven多模块整合spring boot

miaojiangmin
 miaojiangmin
发布于 2017/04/01 09:07
字数 2397
阅读 236
收藏 0

昨天尝试了,spring boot和公司现有的boss系统整合。之前已经有一些模块用spring boot写了,所以这次想更彻底点。但是在整合的时候却遇到了麻烦,很烦恼。 因为我们原来的页面是用jsp写的,spring boot又强烈不推荐用jsp作为展示层。我用的ide是IDEA,jdk1.8,spring boot 1.4.3. 主要问题是在多模块中,项目启动后会有问题,表现为404错误,而我单个模块运行又是好的,我也是醉了,这个问题也不好定位。花了蛮多时间的,查阅了一些文章。但还是并没有解决。 于是我想到了我开发的时候就用原来的模式,但是我部署的时候用spring boot的方式,也就是说,开发和部署分离。(今天上午尝试了一下,并没有成功,问题是因为原来是用spring,spring-mvc来实现了,但是要用spring boot发布就会引入新的java文件和spring boot的相关jar包,即使我用profile划分也还是不可以。) 今天又尝试了一下,404的问题,被我解决了,虽然还是雨点懵,但是找到了解决问题的关键点,在于idea中spring boot的配置,working directory ,配置为 $MODULE_DIR$,(旁边有个快捷键可以选择)。虽然还有其他问题,但是离成功又近了一步。 还有就是在以后架构进化中想采用dubbo与spring boot结合的方式,因为这样更加便于部署。也跟方便整合。 今天尝试了另一种方法,把spring-shiro.xml转化为shiroConfig.java。结果成功了,虽然我也不知道到底是什么原因,但至少是有效的。这点还是不错的,毕竟研究了好几天,尝试过runable-war,但是感觉这种才是最方便的。 我把两种代码晒出来。

####这是spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
       default-lazy-init="true">

    <description>Shiro安全配置</description>

    <!--安全管理器-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--设置自定义Realm-->
        <property name="realm" ref="shiroDbRealm"/>
        <!--将缓存管理器,交给安全管理器-->
        <!--<property name="cacheManager" ref="shiroEhcacheManager"/>-->
        <property name="cacheManager" ref="shiroCacheManager"/>

        <property name="sessionManager" ref="sessionManager" />
        <!-- 记住密码管理 -->
        <property name="rememberMeManager" ref="rememberMeManager"/>
    </bean>


    <bean id="shiroCacheManager" class="com.sanjiang.boss.sys.secure.auth.cache.ShiroCacheManager"></bean>

    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="sessionDAO" ref="sessionDAO"/>
        <property name="globalSessionTimeout"  value="3600000"/>
        <property name="sessionValidationInterval" value="3600000" />
        <property name="sessionValidationSchedulerEnabled" value="true" />
        <!--<property name="sessionIdCookie.name"  value="BOSS_JSESSIONID"/>-->
        <!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->
        <property name="sessionIdCookie" ref="shareSession" />
    </bean>



    <!-- sessionIdCookie的实现,用于重写覆盖容器默认的JSESSIONID -->
    <bean id="shareSession" class="org.apache.shiro.web.servlet.SimpleCookie">
        <!-- cookie的name,对应的默认是 JSESSIONID -->
        <constructor-arg name="name" value="SHAREJSESSIONID" />
        <!-- jsessionId的path为 / 用于多个系统共享jsessionId -->
        <property name="path" value="/" />
        <property name="httpOnly" value="true"/>
    </bean>


    <!--<bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO" >-->
    <bean id="sessionDAO" class="com.mjm.boss.sys.secure.auth.session.ShiroSessionDAO" ></bean>

    <!-- 項目自定义的Realm -->
    <bean id="shiroDbRealm" class="com.mjm.boss.sys.secure.auth.realm.ShiroDbRealm"/>

    <!--<bean id="shiroDbRealm" class="com.sanjiang.boss.portal.task.secure.auth.ShiroDbRealm"/>-->


    <!-- 记住密码Cookie -->
    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="rememberMe"/>
        <property name="httpOnly" value="true"/>
        <!-- 7天,采用spring el计算方便修改[细节决定成败]! -->
        <property name="maxAge" value="#{7 * 24 * 60 * 60}"/>
    </bean>

    <!-- rememberMe管理器,cipherKey生成见{@code Base64Test.java} -->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('5aaC5qKm5oqA5pyvAAAAAA==')}"/>
        <property name="cookie" ref="rememberMeCookie"/>
    </bean>

    <!-- Shiro Filter -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 安全管理器 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 默认的登陆访问url -->
        <property name="loginUrl" value="/login"/>
        <!-- 登陆成功后跳转的url -->
        <property name="successUrl" value="/index"/>
        <!-- 没有权限跳转的url -->
        <property name="unauthorizedUrl" value="/unauth"/>
        <property name="filters">
            <util:map>
                <entry key="membership" value-ref="membershipFilter"/>
                <entry key="authc" >
                    <bean class="com.mjm.boss.sys.secure.auth.filter.ShiroFormAuthenticationFilter"></bean>
                </entry>
            </util:map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                <!--
                    anon  不需要认证
                    authc 需要认证
                    user  验证通过或RememberMe登录的都可以
                -->
                /commons/** = anon
                /static/** = anon
                /webhooks = anon
                /login = anon
                /ic/** = anon
                /excel/upload = anon

                <!--
                    其他 系统 调用 easyreport 报表
                -->
                /report/** = anon
                /assets/** = anon
                /dynamic/** = anon
                /o2o/** = anon

                /** = user
            </value>
        </property>
    </bean>

    <!-- 用户授权信息Cache, 采用EhCache -->
    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
    </bean>

    <!-- 在方法中 注入  securityManager ,进行代理控制 -->
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
        <property name="arguments" ref="securityManager"/>
    </bean>

    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- AOP式方法级权限检查  -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>

    <!-- 启用shrio授权注解拦截方式 -->
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <bean id="membershipFilter" class="com.mjm.boss.sys.secure.auth.filter.MembershipFilter"/>

    <bean id="casSubjectFactory" class="org.apache.shiro.cas.CasSubjectFactory" />
    <!--<bean id="casSubjectFactory" class="org.apache.shiro.mgt.SubjectFactory" />-->


    <!-- shiro  的注解权限配置的异常跳转 -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.apache.shiro.authz.UnauthorizedException">/error/noAuthorization</prop>
                <prop key="org.apache.shiro.authz.UnauthenticatedException">/error/noAuthentication</prop>
            </props>
        </property>
    </bean>
</beans>

####这是ShiroConfiguration

/**
 * Shiro 配置
 * 这样配置后,就可以正常登陆了,不然会报@Autowried错误,应该是没有加载web.xml导致的问题吧
 * 另一种解决方法是加载web.xml,不过有点复杂了
 * Created by mjm on 2017/4/4.
 */
@Configuration
public class ShiroConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);

    /**
     * EhCacheManager,缓存管理,用户登陆成功后,把用户信息和权限信息缓存起来,然后每次用户请求时,放入用户的session中,如果不设置这个bean,每个请求都会查询一次数据库。
     * @return
     */
    @Bean(name = "shiroEhcacheManager")
    public EhCacheManager getEhCacheManager() {
        EhCacheManager em = new EhCacheManager();
        em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
        return em;
    }

    /**
     * HashedCredentialsMatcher,这个类是为了对密码进行编码的,防止密码在数据库里明码保存,当然在登陆认证的生活,这个类也负责对form里输入的密码进行编码。
     * @return
     */
   /* @Bean(name = "hashedCredentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");
        credentialsMatcher.setHashIterations(2);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }*/

    /**
     * ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm,负责用户的认证和权限的处理,可以参考JdbcRealm的实现。
     * @return
     */
    @Bean(name = "shiroDbRealm")
    @DependsOn("lifecycleBeanPostProcessor")
    public ShiroDbRealm getShiroRealm() {

        ShiroDbRealm realm = new ShiroDbRealm();
//        realm.setCredentialsMatcher(hashedCredentialsMatcher());
        return realm;
//        return new ShiroDbRealm();
    }

    /**
     *  LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,负责org.apache.shiro.util.Initializable类型bean的生命周期的,
     *  初始化和销毁。主要是AuthorizingRealm类的子类,以及EhCacheManager类。
     * @return
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }

    /**
     * SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。
     * @return
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager() {
        DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager();
        webSecurityManager.setRealm(getShiroRealm());
        //      <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 -->
        webSecurityManager.setCacheManager(getEhCacheManager());
        return webSecurityManager;
    }

    /**
     * AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类,内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。
     * 老实说,这里注入securityManager,我不知道有啥用,从source上看不出它在什么地方会被调用。
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(getDefaultWebSecurityManager());
        return new AuthorizationAttributeSourceAdvisor();
    }


    /**
     * 加载shiroFilter权限控制规则(从数据库读取然后配置)
     *
     * @author SHANHY
     * @create  2016年1月14日
     */
    private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){
        /////////////////////// 下面这些规则配置最好配置到配置文件中 ///////////////////////
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
        filterChainDefinitionMap.put("/user", "authc");// 这里为了测试,只限制/user,实际开发中请修改为具体拦截的请求规则
        // anon:它对应的过滤器里面是空的,什么都没做
        logger.info("##################从数据库读取权限规则,加载到shiroFilter中##################");

//        filterChainDefinitionMap.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试,固定写死的值,也可以从数据库或其他配置中读取
//        filterChainDefinitionMap.put("/login", "anon");
//        filterChainDefinitionMap.put("/**", "anon");//anon 可以理解为不拦截
//        filterChainDefinitionMap.put("/sa*//**", "authc");
//        filterChainDefinitionMap.put("*//**", "anon");

        //更好的方法是读取数据库或者配置文件,这样可以更加严格,主要是对于url的拦截

        filterChainDefinitionMap.put("/commons/**","anon");
        filterChainDefinitionMap.put("/static/**","anon");
        filterChainDefinitionMap.put("/webhooks","anon");
        filterChainDefinitionMap.put("/login","anon");

        filterChainDefinitionMap.put("/ic/**","anon");
        filterChainDefinitionMap.put("/excel/upload","anon");

//         其他 系统 调用 easyreport 报表
        filterChainDefinitionMap.put("/report/**","anon");
        filterChainDefinitionMap.put("/assets/**","anon");
        filterChainDefinitionMap.put("/dynamic/**","anon");
        filterChainDefinitionMap.put("/o2o/**","anon");
        filterChainDefinitionMap.put("/**","user");


        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    }


    /**
     * 注册DelegatingFilterProxy(Shiro)
     * 集成Shiro有2种方法:
     * 1. 按这个方法自己组装一个FilterRegistrationBean(这种方法更为灵活,可以自己定义UrlPattern,
     * 在项目使用中你可能会因为一些很但疼的问题最后采用它, 想使用它你可能需要看官网或者已经很了解Shiro的处理原理了)
     * 2. 直接使用ShiroFilterFactoryBean(这种方法比较简单,其内部对ShiroFilter做了组装工作,无法自己定义UrlPattern,
     * 默认拦截 /*)
     *
     */
    //  @Bean
    //  public FilterRegistrationBean filterRegistrationBean() {
    //      FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
    //      filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));
    //      //  该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理
    //      filterRegistration.addInitParameter("targetFilterLifecycle", "true");
    //      filterRegistration.setEnabled(true);
    //      filterRegistration.addUrlPatterns("/*");// 可以自己灵活的定义很多,避免一些根本不需要被Shiro处理的请求被包含进来
    //      return filterRegistration;
    //  }

    /**
     * ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。
     * @return
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean
                .setSecurityManager(getDefaultWebSecurityManager());

        Map<String, Filter> filters = new LinkedHashMap<>();
        LogoutFilter logoutFilter = new LogoutFilter();
        logoutFilter.setRedirectUrl("/login");
        filters.put("logout", logoutFilter);


        filters.put("membership",getMemberShipFilter());
        filters.put("authc",getShiroFormAuthenticationFilter());



        shiroFilterFactoryBean.setFilters(filters);
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");




        loadShiroFilterChain(shiroFilterFactoryBean);

        return shiroFilterFactoryBean;
    }

    @Bean("membershipFilter")
    public MembershipFilter getMemberShipFilter(){
        return new MembershipFilter();
    }

    @Bean("formAuthenticationFilter")
    public ShiroFormAuthenticationFilter getShiroFormAuthenticationFilter(){
        return new ShiroFormAuthenticationFilter();
    }

    /**
     *  shiro  的注解权限配置的异常跳转
     * @return
     */
    @Bean("simpleMappingExceptionResolver")
    public SimpleMappingExceptionResolver getSimpleMappingExceptionResolver(){
        SimpleMappingExceptionResolver exceptionResolver = new  SimpleMappingExceptionResolver();

        Properties properties = new Properties();
        properties.setProperty("org.apache.shiro.authz.UnauthorizedException","/error/noAuthorization");
        properties.setProperty("org.apache.shiro.authz.UnauthenticatedException","/error/noAuthentication");

        exceptionResolver.setExceptionMappings(properties);
        return exceptionResolver;
    }

    /**
     * 在方法中 注入  securityManager ,进行代理控制
     * 加入,启动会报错
     */
   /* @Bean("methodInvokingFactoryBean")
    public MethodInvokingFactoryBean getMethodInvokingFactoryBean(){
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
        methodInvokingFactoryBean.setArguments(new Object[]{"securityManager"});

        return methodInvokingFactoryBean;
    }*/

    /**
     * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
     * @return
     */
   /* @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }*/
}

围绕spring boot的生态日渐成熟,对于原来的项目想采用spring boot的开发的愿求也越来越强烈。特别想用spring cloud中的一些特性,这样才能更加更好的扩展起来。比如开发一个api网关,这样其他应用调用的api的时候就可以更好的把系统中api开放出来。

© 著作权归作者所有

上一篇: vim
下一篇: vagrant学习笔记
miaojiangmin
粉丝 15
博文 471
码字总数 115861
作品 0
宁波
程序员
私信 提问
maven子模块适合使用spring boot吗?

单模块的情况下,Spring Boot的配置非常简单。但在maven多模块中,Spring Boot真的很不友好。 第一,Application的注解需要显式添加 否则,入口模块以外的模块无法被识别。 第二,引入其余框...

itwriter
2018/08/08
440
2
IntelliJ IDEA Spring Boot 2.x 多模块项目创建

在学习Spring Boot 2的时候顺便来学习创建下Maven下的多模块项目创建。方便学习使用整套开发流程。 第一步,检查IDEA,新版本的IDEA可能没有Spring Assistant可通过插件安装(Preferences->P...

被猪拱了的JAVA
07/16
156
0
SpringBoot多模块项目实践(Multi-Module)

序言: 比起传统复杂的单体工程,使用Maven的多模块配置,可以帮助项目划分模块,鼓励重用,防止POM变得过于庞大,方便某个模块的构建,而不用每次都构建整个项目,并且使得针对某个模块的特...

覃光林
07/03
134
0
springboot|解决:mvn多模块下filter配置替换

问题:之前的mvn多模块项目,我会在parent模块下,创建几个filter配置文件,以实现不同环境不同配置。但是在搭建springboot的mvn多模块框架时,配置文件始终替换不了。 原因:仔细看springb...

云胜886
2018/07/31
0
0
一步步实现web程序信息管理系统之二--后台框架实现跳转登陆页面

SpringBoot springboot的目的是为了简化spring应用的开发搭建以及开发过程。内部使用了特殊的处理,使得开发人员不需要进行额外繁锁的xml文件配置的编写,其内部包含很多模块的配置只需要添加...

编程SHA
2018/11/08
109
0

没有更多内容

加载失败,请刷新页面

加载更多

springboot 403 问题

添加WebAppConfigurer 配置 @Configuration@EnableAutoConfigurationpublic class WebAppConfigurer extends WebMvcConfigurerAdapter { public WebAppConfigurer() { } ......

布袋和尚_爱吃鱼
23分钟前
3
0
Python自动更换壁纸爬虫与tkinter结合

直接上代码 import ctypesimport timeimport requestsimport osfrom threading import Threadfrom tkinter import Tk, Label, Button,Entry,StringVar,messagebox# '放到AppData\Roami......

物种起源-达尔文
23分钟前
3
0
Postgresql Study 笔记

Postgresql 安装 Windows, MAC Install Postgresql 下载地址: https://www.enterprisedb.com/downloads/postgres-postgresql-downloads Linux Install sudo apt-get update sudo apt-get in......

slagga
25分钟前
3
0
layer.open 打开新页面传参问题

如图所示,点击出售,把A页面的数据传到弹框上面,因为弹框比较复杂,所以使用引入一个新页面。 A.html a.js B.html b.js 1、第一种方案 sellInte: function (){ var obj = document.g...

木九天
28分钟前
4
0
沙龙报名 | 区块链数据服务技术应用实践

京东云是国内首家提供区块链数据在线分析服务产品的公司,也是行业内首家对区块链数据服务进行开源的公司。 本次沙龙是京东云BDS开源后,首次在深圳举办线下沙龙,我们将邀请京东云BDS团队核...

京东云技术新知
29分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部