apache shiro 简介
shiro是Apache退出的认证授权框架,帮我们封装了认证授权接口,我们只需要实现这些接口即可,不需要关心回话管理授权及拦截等功能.springdata 简介
springdata使用了jpa规范底层实现使用hibernate,本文中全部使用标注完全面向对象
springdata是spring提供的类似于hibernatedao,可以帮助我们快速开发,完全面向对象操作,是基于jpa规范的orm框架,提供了丰富的对象查询保存更新方法.swagger简介
swagger是基于springmvc开发的接口测试框架,具有集成简单,提供了丰富的web测试页面,可以帮助我们快速开发web项目.测试接口等.废话不多说了,直接贴代码
从最基本的 入口开始 由于是基于springboot 的配置,所以maven配置文件中有spring.bootjar,基于springboot,我们可以不需要关心太多的jar, springboot本身集成了spring核心和springmvc等 pom.xml如下
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sa.oversea</groupId>
<artifactId>IntegrationPlatformManagement</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<jdbc.postgresql>9.2-1002.jdbc4</jdbc.postgresql>
<slf4j.version>1.7.7</slf4j.version>
<junit.version>4.11</junit.version>
<swagger.spring.version>1.0.2</swagger.spring.version>
<swagger.version>2.1.8-M1</swagger.version>
<swagger.annotation.version>1.3.1</swagger.annotation.version>
<aspectj.version>1.8.6</aspectj.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.spring>4.2.5.RELEASE</version.spring>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.3.3.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<artifactId>tomcat-embed-el</artifactId>
<groupId>org.apache.tomcat.embed</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>1.3.3.RELEASE</version>
<exclusions>
<exclusion>
<artifactId>tomcat-jdbc</artifactId>
<groupId>org.apache.tomcat</groupId>
</exclusion>
<exclusion>
<artifactId>spring-expression</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.191</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.8</version>
</dependency>
<dependency>
<groupId>com.mangofactory</groupId>
<artifactId>swagger-springmvc</artifactId>
<version>${swagger.spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>postgre</groupId>
<artifactId>postgresql</artifactId>
<version>9.2-1002.jdbc4</version>
</dependency>
<!--> shiro <! -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.2.Final</version>
</dependency>
</dependencies>
</project>
由于是零配置,当然入口不是web.xml了web.xml里面只配置了项目欢迎页,就不贴了 看代码,入口由于是零配置,需要servlet3.1才支持的
@Order(1)
public class WebConfig implements WebApplicationInitializer{
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//servletContext.addListener(new DbStarter());
//OpenSessionInViewFilter
/* OpenSessionInViewFilter hibernateSessionInViewFilter = new OpenSessionInViewFilter();
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter(
"hibernateFilter", hibernateSessionInViewFilter);
filterRegistration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/");
*/
/*DelegatingFilterProxy shiroFilter=new DelegatingFilterProxy();
shiroFilter.setTargetFilterLifecycle(true);
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter(
"shiroFilter", shiroFilter);
filterRegistration.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/*");*/
}
}
WebConfig 类似于web.xml 可以监听tomcat启动然后装载需要的filter和servlet
再来看如何整合spring的由于使用了零配置,所有spring帮我们集成了filter和servlet的接口,只需要实现这些接口将配置信息注入即可
@Order(2)
public class SpringConfigInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer implements WebApplicationInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { AppConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MvcConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new OpenEntityManagerInViewFilter() };
}
}
//标注我就不讲了,大家去查查标注使用就知道了,最关键的就是@Configuration,@Import({RepositoryConfig.class})
@Configuration
@ComponentScan(basePackages = "com.sa.oversea")
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Import({RepositoryConfig.class})
public class AppConfig {
}
@Configuration@EnableWebMvc@ComponentScan(basePackages = "com.sa.oversea", useDefaultFilters = false, includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = {Controller.class})})public class MvcConfig extends WebMvcConfigurationSupport {@Bean public ViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setPrefix("/WEB-INF/views/"); viewResolver.setSuffix(".jsp"); return viewResolver; } @Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("config.messages.messages"); return messageSource; } @Bean public HandlerAdapter servletHandlerAdapter(){ return new SimpleServletHandlerAdapter(); } @Bean public LocaleChangeInterceptor localeChangeInterceptor(){ return new LocaleChangeInterceptor(); } @Bean(name="localeResolver") public CookieLocaleResolver cookieLocaleResolver(){ return new CookieLocaleResolver(); } @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { return super.requestMappingHandlerMapping(); } @Bean public MappingJackson2HttpMessageConverter converter() { MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter(); List<MediaType> supportedMediaTypes = new ArrayList<MediaType>(); supportedMediaTypes.add(new MediaType("text", "plain")); supportedMediaTypes.add(new MediaType("application", "json")); jsonMessageConverter.setSupportedMediaTypes(supportedMediaTypes); return jsonMessageConverter; } @Override protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(localeChangeInterceptor()); } @Bean public HandlerMapping resourceHandlerMapping() { return super.resourceHandlerMapping(); } @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("/WEB-INF/static/"); registry.addResourceHandler("/**").addResourceLocations("/resources/api/"); } @Bean(name="multipartResolver") public CommonsMultipartResolver commonsMultipartResolver(){ return new CommonsMultipartResolver(); } @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { return super.requestMappingHandlerAdapter(); } }
数据源的配置代码
public interface DataSourceConfig {
public DataSource load();
}
public class PostgreSQLConfig implements DataSourceConfig{
@Resource
private Environment env;
//
@Override
@Bean
public DataSource load() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUsername(env.getProperty("jdbc.postgresql.username"));
dataSource.setUrl(env.getProperty("jdbc.postgresql.url"));
dataSource.setPassword(env.getProperty("jdbc.postgresql.password"));
dataSource.setDriverClassName(env.getProperty("jdbc.postgresql.driver"));
dataSource.setInitialSize(Integer.valueOf(env.getProperty("dbcp.initSize")));
dataSource.setMaxTotal(Integer.valueOf(env.getProperty("dbcp.maxTotal")));
dataSource.setMaxIdle(Integer.valueOf(env.getProperty("dbcp.maxIdle")));
dataSource.setMinIdle(Integer.valueOf(env.getProperty("dbcp.minIdle")));
return dataSource;
}
}
@Configuration@EnableTransactionManagement(proxyTargetClass = true)@PropertySources(@PropertySource("classpath:properties/database.properties"))@Import({ PostgreSQLConfig.class })@EnableJpaRepositories(basePackages = "com.sa.oversea.**.repo")public class RepositoryConfig {@Resourceprivate Environment environment;@Resourceprivate DataSource datasource;@Beanpublic Properties loadHibernateProperties() {Properties properties = new Properties();properties.put("hibernate.dialect",environment.getRequiredProperty("hibernate.dialect"));properties.put("hibernate.show_sql",environment.getRequiredProperty("hibernate.show_sql"));properties.put("hibernate.format_sql",environment.getRequiredProperty("hibernate.format_sql"));properties.put("hibernate.hbm2ddl.auto",environment.getRequiredProperty("hibernate.hbm2ddl.auto"));return properties;}@Beanpublic PlatformTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory){return new JpaTransactionManager(entityManagerFactory.getObject());}@Bean(name ="entityManagerFactory")public LocalContainerEntityManagerFactoryBean entityManagerFactory(){LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();vendorAdapter.setGenerateDdl(Boolean.TRUE);vendorAdapter.setShowSql(Boolean.TRUE);factory.setDataSource(datasource);factory.setJpaVendorAdapter(vendorAdapter);factory.setPackagesToScan("com.sa.oversea.**.entities");factory.setJpaProperties(loadHibernateProperties());factory.afterPropertiesSet();factory.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());return factory;}}
swagger 配置 相当简单如下
@Configuration
@EnableSwagger
@ComponentScan(basePackages = {"com.sa.oversea"})
public class MySwaggerConfig
{
private SpringSwaggerConfig springSwaggerConfig;
/**
* Required to autowire SpringSwaggerConfig
*/
@Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig)
{
this.springSwaggerConfig = springSwaggerConfig;
}
/**
* Every SwaggerSpringMvcPlugin bean is picked up by the swagger-mvc
* framework - allowing for multiple swagger groups i.e. same code base
* multiple swagger resource listings.
*/
@Bean
public SwaggerSpringMvcPlugin customImplementation()
{
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig).apiInfo(apiInfo()).includePatterns(
".*?");
}
private ApiInfo apiInfo()
{
ApiInfo apiInfo = new ApiInfo(
"opportunity of business - system",
"--",
"Web API terms of service",
"any question @javagyb",
null,
null);
return apiInfo;
}
}
当然swagger还需要下载页面的war包,否则无法查看,至于swagger如何使用我这里就不多说了,
apache shiro配置如下
package com.sa.oversea.ipm.config;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.sa.oversea.ipm.security.realm.JPAShiroRealm;
/**
*
* @author javagyb
*
*/
@Configuration
public class ShiroConfiguration {
/* @Bean
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
return em;
} */
@Bean
public Realm getShiroRealm() {
JPAShiroRealm realm = new JPAShiroRealm();
// realm.setCacheManager(getEhCacheManager());
return realm;
}
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
return daap;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm,SessionManager sessionManager) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(realm);
// <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 -->
// dwsm.setCacheManager(getEhCacheManager());
dwsm.setSessionManager(sessionManager);
return dwsm;
}
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(securityManager);
return aasa;
}
/**
* 加载shiroFilter权限控制规则(从数据库读取然后配置)
*
* @author javagyb
*/
private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// filterChainDefinitionMap.put("/securitry/**", "anon");
// filterChainDefinitionMap.put("/api/**", "anon");
// filterChainDefinitionMap.put("/favicon.ico", "anon");
// filterChainDefinitionMap.put("/api-docs/**", "anon");
// filterChainDefinitionMap.put("/lib/**", "anon");
// filterChainDefinitionMap.put("/**", "authc");
// filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "anon");
/* filterChainDefinitionMap.put("/mydemo/login", "anon");
filterChainDefinitionMap.put("/mydemo/getVerifyCodeImage", "anon");
filterChainDefinitionMap.put("/main**", "authc");
filterChainDefinitionMap.put("/user/info**", "authc");
filterChainDefinitionMap.put("/admin/listUser**", "authc,perms[admin:manage]");*/
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
/**
* ShiroFilter<br/>
* @param stuService
* @return
* @author javagyb
* @create 2016年1月14日
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/resources/login.html");
shiroFilterFactoryBean.setUnauthorizedUrl("/");
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
// shiroFilterFactoryBean.setLoginUrl("/login/index.html");
//shiroFilterFactoryBean.setUnauthorizedUrl("/403");
loadShiroFilterChain(shiroFilterFactoryBean);
return shiroFilterFactoryBean;
}
@Bean
public SessionDAO getMemorySessionDAO(){
return new MemorySessionDAO();
}
@Bean
public MethodInvokingFactoryBean setSecurityManager(DefaultWebSecurityManager securityManager){
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager");
methodInvokingFactoryBean.setArguments(ArrayUtils.toArray(securityManager));
return methodInvokingFactoryBean;
}
@Bean
public SessionManager getSessionMangaer(SessionDAO sessionDAO){
DefaultSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionDAO(sessionDAO);
return sessionManager;
}
}
特别强调 swagger 配置一定要再mvc配置后面这样swagger才能发现接口否则会看不到测试接口的,spring配置加载是有顺序加载的.