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如下
4.0.0
com.sa.oversea
IntegrationPlatformManagement
0.0.1-SNAPSHOT
war
9.2-1002.jdbc4
1.7.7
4.11
1.0.2
2.1.8-M1
1.3.1
1.8.6
UTF-8
4.2.5.RELEASE
org.springframework.boot
spring-boot-starter-web
1.3.3.RELEASE
org.springframework.boot
spring-boot-starter-tomcat
tomcat-embed-el
org.apache.tomcat.embed
org.springframework.boot
spring-boot-starter-data-jpa
1.3.3.RELEASE
tomcat-jdbc
org.apache.tomcat
spring-expression
org.springframework
com.h2database
h2
1.4.191
org.projectlombok
lombok
1.16.8
com.mangofactory
swagger-springmvc
${swagger.spring.version}
org.apache.commons
commons-dbcp2
2.1.1
org.apache.commons
commons-dbcp2
2.1.1
commons-fileupload
commons-fileupload
1.2.2
javax.servlet
javax.servlet-api
3.1.0
postgre
postgresql
9.2-1002.jdbc4
shiro
org.apache.commons
commons-lang3
3.4
commons-collections
commons-collections
3.2.1
org.apache.shiro
shiro-spring
1.2.3
org.apache.shiro
shiro-ehcache
1.2.3
org.apache.shiro
shiro-quartz
1.2.3
org.hibernate
hibernate-validator
5.0.2.Final
由于是零配置,当然入口不是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 supportedMediaTypes = new ArrayList();
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 {
@Resource
private Environment environment;
@Resource
private DataSource datasource;
@Bean
public 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;
}
@Bean
public 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);
//
// 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 filterChainDefinitionMap = new LinkedHashMap();
// 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
* @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配置加载是有顺序加载的.