Spring Boot Test:没有定义[javax.persistence.EntityManagerFactory]类型的限定bean

时间:2014-06-08 09:36:10

标签: hibernate spring-mvc hsqldb spring-boot spring-java-config

我正在尝试在spring boot下设置测试上下文,所以我定义了一个TestApplicationContext,如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {MvcConfig.class,SecurityConfig.class})
@WebAppConfiguration
@EnableAutoConfiguration
@PropertySource({ "classpath:persistence.properties" })
@ComponentScan
public class TestApplicationContext {

    @Autowired
    private Environment env;

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
        factory.setPort(9000);
        factory.setSessionTimeout(10, TimeUnit.MINUTES);
        //factory.addErrorPages(new ErrorPage(HttpStatus.404, "/notfound.html"));
        return factory;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);
    return transactionManager;
    }


    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
       LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
       em.setDataSource(hsqlDataSource());
       em.setPackagesToScan(new String[] { "com.touchcorp.touchppoint.model" });

       JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
       em.setJpaVendorAdapter(vendorAdapter);
       em.setJpaProperties(buildHibernateProperties());

       return em;
    }

    @Bean
    public DataSource hsqlDataSource()
    {
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName(org.hsqldb.jdbcDriver.class.getName());
        basicDataSource.setUsername("sa");
        basicDataSource.setPassword("");
        basicDataSource.setUrl("jdbc:hsqldb:mem:mydb");
        return basicDataSource;
    }

    /**
     *
     * Loading all the hibernate properties from a properties file
     */
    protected Properties buildHibernateProperties()
    {
        Properties hibernateProperties = new Properties();

        hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
        hibernateProperties.setProperty("hibernate.show_sql", "true");
        hibernateProperties.setProperty("hibernate.use_sql_comments", "true");
        hibernateProperties.setProperty("hibernate.format_sql", "true");
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create-drop");

        hibernateProperties.setProperty("hibernate.generate_statistics", env.getProperty("hibernate.generate_statistics"));

        hibernateProperties.setProperty("javax.persistence.validation.mode", env.getProperty("javax.persistence.validation.mode"));

        //Audit History flags
        hibernateProperties.setProperty("org.hibernate.envers.store_data_at_delete", env.getProperty("org.hibernate.envers.store_data_at_delete"));
        hibernateProperties.setProperty("org.hibernate.envers.global_with_modified_flag", env.getProperty("org.hibernate.envers.global_with_modified_flag"));

        return hibernateProperties;
    }

}

哪个尝试建立自己的持久化上下文,所以我可以运行这样的测试:

@RunWith(SpringJUnit4ClassRunner.class)
public class ApplicationIntegrationTest extends TestApplicationContext {

    MockMvc mockMvc;

    @Autowired
    private WebApplicationContext wac;

    @Resource(name="springSecurityFilterChain")
    private FilterChainProxy springSecurityFilterChain;

    @Before
    public void setup() {
        // using the web application to initiate the mock
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilter(springSecurityFilterChain).build();


    }

    @Test
    public void thatViewBootstrapUsesHttpNotFound() throws Exception {

        MvcResult result = mockMvc.perform(post("/login")
                .param("username", "user").param("password", "password")).andReturn();
        Cookie c = result.getResponse().getCookie("my-cookie");
        assertThat(c.getValue().length(), greaterThan(10));

        // No cookie; 401 Unauthorized
        mockMvc.perform(get("/")).andExpect(status().isUnauthorized());

        // With cookie; 200 OK
        mockMvc.perform(get("/").cookie(c)).andExpect(status().isOk());

        // Logout, and ensure we're told to wipe the cookie
        result = mockMvc.perform(delete("/session")).andReturn();
        c = result.getResponse().getCookie("my-cookie");
        assertThat(c.getValue().length(), is(0));
    }

}

现在这一切都得到了一个hibernate HSQLDB userDao的支持,它由DeviceUsernamePasswordAuthenticationProvider调用

@Service(value="customAuthenticationProvider")
public class DeviceUsernamePasswordAuthenticationProvider implements AuthenticationProvider {
    private static final Logger LOG = LoggerFactory.getLogger(DeviceUsernamePasswordAuthenticationProvider.class);

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Autowired
    private DeviceDetailsService deviceDetailsService;

    @Override
    public boolean supports(Class<? extends Object> authentication) {
        return authentication.equals(DeviceUsernamePasswordAuthenticationToken.class);
    }

    /**
     * Implements authentication with a number of scenarios in mind:
     * <ul>
     *     <li>A non-browser client is making a request without device details - FAIL</li>
     *     <li>A non-browser client is making a request with device details in the request  - CHECK
     *     if successful a TOKEN is set</li>
     *     <li>A non-browser client is making a request with device TOKEN  - CHECK</li>
     *     <li>A browser client is making a request with device TOKEN or device details with user and password  - CHECK
     *     if successful JSESSIONID is set</li>
     * </ul>
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        LOG.info("Authenticating device and user - assigning authorities...");
        DeviceUsernamePasswordAuthenticationToken auth = (DeviceUsernamePasswordAuthenticationToken) authentication;
        String name = auth.getName();
        String password = auth.getCredentials().toString();

        boolean isDeviceRequest = (name == null && password == null);
        LOG.debug("name is {}, password is {}", name, password);

        // (a) nothing, (b) hasToken|<token encoding>, or (c) getToken|<base64 encoded device request>
        String deviceToken = auth.getDeviceAuthorisation();

        if (deviceToken == null) {
            // very bad - set as anonymous
            LOG.error("missing.device.token");
            throw new BadCredentialsException("missing.device.token");
        }

        LOG.debug("deviceToken is {}", deviceToken);
        String[] deviceInformation = StringUtils.split(deviceToken,"|");


        DeviceDetails device = null;

        if(deviceInformation[0].equals("getToken")) {
            LOG.debug("getToken");
            // we expect the array to be of length 3, if not, the request is malformed
            if (deviceInformation.length < 3) {
                LOG.error("malformed.device.token");
                throw new BadCredentialsException("malformed.device.token");
            }

            device = deviceDetailsService.loadDeviceByDeviceId(deviceInformation[1]);

            if (device == null) {
                LOG.error("missing.device");
                throw new BadCredentialsException("missing.device");
            } else {
                // otherwise, get the authorities
                auth = new DeviceUsernamePasswordAuthenticationToken(null, null,
                        device.getDeviceId(), device.getAuthorities());

                //also we need to set a new token into the database

                String newToken = Hashing.sha256()
                        .hashString("your input", Charsets.UTF_8)
                        .toString();


                deviceDetailsService.setToken(device.getDeviceId(),newToken);

                // and put it into the response headers
                auth.setDeviceTokenForHeaders(newToken);

            }
        } else if(deviceInformation[0].equals("hasToken")) {
            LOG.debug("hasToken");
            if (deviceInformation.length < 3) {
                LOG.error("malformed.device.token");
                throw new BadCredentialsException("malformed.device.token");
            }

            // check that there is a token and that the token has not expired
            String token = deviceDetailsService.getToken(deviceInformation[1]);

            if (token == null) {
                // we got a token in the request but the token we have no stored token
                LOG.error("mismatched.device.token");
                throw new BadCredentialsException("mismatched.device.token");
            } else if(!token.equals(deviceInformation[2])) {
                // we got a token in the request and its not the same as the token we have stored
                LOG.error("mismatched.device.token");
                throw new BadCredentialsException("mismatched.device.token");
            } else if ( deviceDetailsService.hasTokenExpired(deviceInformation[1])) {
                // we got a token in the request and its not the same as the token we have stored
                LOG.error("expired.device.token");
                throw new BadCredentialsException("expired.device.token");
            } else {
                // token was in the request, correctly formed, and matches out records
                device = deviceDetailsService.loadDeviceByDeviceId(deviceInformation[1]);
                auth = new DeviceUsernamePasswordAuthenticationToken(null, null,
                        device.getDeviceId(), device.getAuthorities());
            }


        } else {
            LOG.error("malformed.device.token");
            throw new BadCredentialsException("malformed.device.token");
        }

        if (!isDeviceRequest) {

            // OK, now we can do the user stuff




            UserDetails user = customUserDetailsService.loadUserByUsername(name);
            auth = new DeviceUsernamePasswordAuthenticationToken(name, password, device.getDeviceId(), device.getAuthorities());
        }

        return auth;
    }

}

使用CustomUserDetailsS​​ervice,如下所示:

@Service(value="customUserDetailsService")
@Transactional(readOnly=true)
public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {

    private static final Logger LOG = LoggerFactory.getLogger(CustomUserDetailsServiceImpl.class);

    @Autowired
    private UserDao userDao;



    public UserDetails loadUserByUsername(String login)
            throws UsernameNotFoundException {
        LOG.info("Finding the UserDetails for {}", login);

        com.touchcorp.touchpoint.model.domain.User domainUser = userDao.getUser(login);

        if(domainUser == null) {
            throw new UsernameNotFoundException("The user {} was not found", login);
        }

        boolean enabled = true;
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        return new User(
                domainUser.getLogin(),
                domainUser.getPassword(),
                enabled,
                accountNonExpired,
                credentialsNonExpired,
                accountNonLocked,
                getAuthorities(domainUser.getRoles())
        );
    }


    public Collection<? extends GrantedAuthority> getAuthorities(List<Role> roles) {
        List<GrantedAuthority> authorities = new ArrayList<>();
        LOG.debug("List of Authorities...");
        for (Role role : roles) {

            StringBuilder bob = new StringBuilder("ROLE_");
            bob.append(role.getRole().toUpperCase());
            LOG.debug("authority {}",bob.toString());
            authorities.add(new SimpleGrantedAuthority(bob.toString()));
        }

        return authorities;
    }

}

调用userDao ..

@Repository("userDao")
public class UserDaoImpl implements UserDao {
    private static final Logger LOG = LoggerFactory.getLogger(UserDaoImpl.class);

    @PersistenceContext
    private EntityManager entityManager;

    public User getUser(String login) {
        LOG.debug("Looking for a user with login: {}", login);

        List<User> list = entityManager.createQuery(
                                "SELECT u FROM User u WHERE u.login = :login")
                        .setParameter("login", login).getResultList( );
                return (list.isEmpty( )?null:list.get( 0 ));
    }

}

问题是容器无法启动,而是抛出邪恶的BeanCreationException。

这是跨越各个层的堆栈跟踪

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customAuthenticationProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.touchcorp.touchpoint.service.CustomUserDetailsService com.touchcorp.touchpoint.security.DeviceUsernamePasswordAuthenticationProvider.customUserDetailsService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customUserDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.touchcorp.touchpoint.model.dao.UserDao com.touchcorp.touchpoint.service.CustomUserDetailsServiceImpl.userDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1017)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
    ... 45 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.touchcorp.touchpoint.service.CustomUserDetailsService com.touchcorp.touchpoint.security.DeviceUsernamePasswordAuthenticationProvider.customUserDetailsService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customUserDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.touchcorp.touchpoint.model.dao.UserDao com.touchcorp.touchpoint.service.CustomUserDetailsServiceImpl.userDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    ... 56 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customUserDetailsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.touchcorp.touchpoint.model.dao.UserDao com.touchcorp.touchpoint.service.CustomUserDetailsServiceImpl.userDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1017)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
    ... 58 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.touchcorp.touchpoint.model.dao.UserDao com.touchcorp.touchpoint.service.CustomUserDetailsServiceImpl.userDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    ... 69 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:356)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1017)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
    ... 71 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:559)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:515)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:682)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:655)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:155)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:353)
    ... 82 more

有谁知道我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {MvcConfig.class,SecurityConfig.class})
@WebAppConfiguration

这3行对你的配置类没有任何意义。它应该用@Configuration注释,那3行应该在你的测试类上。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestApplicationContext.class)
@WebAppConfiguration
public class ApplicationIntegrationTest { … }

the testing部分的弹簧启动参考指南中也对此进行了解释。

答案 1 :(得分:0)

我讨论过回答我自己的问题,但我想如果我对原帖进行了编辑,那会让事情有点混乱。在beebajay的评论之后,我修改了TestApplicationContext和ApplicationIntegrationTest来读取:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {MvcConfig.class,SecurityConfig.class})
@WebAppConfiguration
@EnableAutoConfiguration
@PropertySource({ "classpath:persistence.properties" })
@ComponentScan
public class TestApplicationContext {

    @Autowired
    private Environment env;

// body same as before
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestApplicationContext.class,MvcConfig.class,SecurityConfig.class})
public class ApplicationIntegrationTest {

    MockMvc mockMvc;

    @Autowired
    private WebApplicationContext wac;

    @Resource(name="springSecurityFilterChain")
    private FilterChainProxy springSecurityFilterChain;

// rest same as before
}

但是发生的事情是我已经退回一步并且ApplicationIntegrationTest不再编译,抱怨它无法解析名为“springSecurityFilterChain”的bean

我认为配置时暗示了这一点:

@Configuration
@EnableWebMvcSecurity
@ComponentScan({
        "com.touchcorp.touchpoint.security",
        "com.touchcorp.touchpoint.service",
        "com.touchcorp.touchpoint.model.dao"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    DeviceUsernamePasswordAuthenticationProvider customAuthenticationProvider;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth
                .authenticationProvider(customAuthenticationProvider);
    }

    @Configuration
    @Order(1)
    public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
            http
                .antMatcher("/api/**")
                    .authorizeRequests()
                .anyRequest().hasRole("ADMIN")
                    .and()
                    .httpBasic();
        }
    }

    @Order(2)
    @Configuration
    public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .csrf().disable()
                .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                .loginPage("/login")
                    .failureUrl("/login?error=1")
                    .permitAll()
                    .and()
                .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/");
        }
    }

    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
                .addResourceHandler("/resources/**")
                .addResourceLocations("/resources/")
                .setCachePeriod(31556926);
    }

再次抱歉用一个问题回答我的问题,但如果我这样做是为了编辑,我认为它会变得非常混乱。