一 加载配置文件内容
1.1 普通读取
1.1.1 class文件
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
@Value("${jdbc.driver}")
String driverClassName;
@Value("${jdbc.url}")
String url;
@Value("${jdbc.username}")
String username;
@Value("${jdbc.password}")
String password;
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
1.1.2 配置文件(jdbc.properties)
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.username=arya
jdbc.password=arya
1.2 简洁方式(自动注入)
1.2.1 Java文件
@Configuration
public class JdbcPoConfig {
// 配置文件必须为application.yml,以下JdbcPropertiePo 的实体类自动自动注入
@Bean
@ConfigurationProperties(prefix = "jdbcpo")
public JdbcPropertiePo jdbcPropertiePo(){
return new JdbcPropertiePo();
}
}
1.2.2 yml文件
jdbcpo:
url: url连接
driverClassName: driverClassName名称
username: username1
password: password1
1.3 引入多个配置文件
1.3.1 application.yml激活
spring:
profiles:
active: abc
1.3.2 在application-abc.yml中添加内容,文件命名格式:前缀必须为application,后面是“-”
user:
filepath: 12346
uname: "13"
1.3.3 controller中测试
@Value("${user.filepath}")
private String filepath;
1.4 修改端口
server:
port: 8083
1.5 加载静态文件的路径
1.5 配置拦截器
1.5.1 书写拦截器
public class MyIntercepor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("--------preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("--------postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("--------afterCompletion");
}
1.5.2 注入拦截器
@Configuration
public class MvcConfig implements WebMvcConfigurer {
// 注册拦截器
@Bean
public MyIntercepor myIntercepor(){
return new MyIntercepor();
}
// 添加拦截器到spring MVC拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myIntercepor()).addPathPatterns("/*");
}
}
1.6 配置数据源
1.6.1如果是自定义数据源则需要在run开头写(exclude= {DataSourceAutoConfiguration.class})
如下:
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
public class BootDemoApplication {
// psvm
public static void main(String[] args) {
SpringApplication.run(BootDemoApplication.class,args);
}
}
1.6.2 默认的数据源
application.yml文件
spring:
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@localhost:1521:orcl
username: arya
password: arya
配置连接池,使用自定义的需使用第一种方法
spring:
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@localhost:1521:orcl
username: arya
password: arya
type: com.alibaba.druid.pool.DruidDataSource
2 springBoot使用Mybatis
2.1 使用注解版
2.1.1 配置阿里巴巴Druid连接池
@Configuration
public class JdbcPoConfig {
@ConfigurationProperties(prefix = "jdbcpo")
@Bean
public DruidDataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1 配置一个管理后台的servlet
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123");
initParams.put("allow","");//默认就是允许所有访问
//initParams.put("deny","localhost");
bean.setInitParameters(initParams);
return bean;
}
//2 配置web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
监控如图
2.1.2 书写DAO层
@Mapper
public interface UserMapper {
@Select(("select * from SYS_USER where id = #{id}"))
public User getUserById(String id);
@Delete("delete from SYS_USER WHERE ID =#{id}")
public int deleteById(String id);
@Insert(("insert into SYS_USER (NAME) VALUES(#{name})"))
public int inserUser(User user);
@Update("update SYS_USER SET NAME = #{name} where id =#{id}")
public int updateUser(User user);
}
2.1.3 至此已完成配置,将dao引入到service层调用即可,还可以用扫描Dao的方法注入
在启动类中书写如下
@SpringBootApplication
@MapperScan("com.msun.dao")
public class BootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(BootDemoApplication.class,args);
}
}
2.2 使用配置版(非注解)mybatis
2.2.1 dao层
public interface UserDao {
public User getUserById(String id);
}
2.2.2 xml结构图
2.2.3 mybatis-config.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!-- 駝峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
</configuration>
2.2.4 userMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?> select * from SYS_USER where id = #{id}2.2.5 yml文件指定mybatis扫描路径
mybatis:
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
三 配置shiro
3.1 shiro配置
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//拦截器.
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
//配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("logout", "logout");
//filterChainDefinitionMap.put("/user/login", "anon");
// authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/user/login/**", "anon");
// filterChainDefinitionMap.put("/**", "authc");//对所有请求就拦截
// filterChainDefinitionMap.put("/page/**", "authc"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/login.html");
shiroFilterFactoryBean.setUnauthorizedUrl("/page/fail.html");//未授权跳转
//登录成功跳转的链接 (这个不知道怎么用,我都是自己实现跳转的)
shiroFilterFactoryBean.setSuccessUrl("/page/main.html");
shiroFilterFactoryBean.setLoginUrl("/user/login/");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 凭证匹配器
* 由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
* @return
*/
// @Bean
// public HashedCredentialsMatcher hashedCredentialsMatcher() {
// HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
// hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
// return hashedCredentialsMatcher;
// }
@Bean
public UserRealm myShiroRealm() {
UserRealm myShiroRealm = new UserRealm();
//使用加密
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();;
//设置加密算法为md5
credentialsMatcher.setHashAlgorithmName("MD5");
//设置散列次数
credentialsMatcher.setHashIterations(1024);
myShiroRealm.setCredentialsMatcher(credentialsMatcher);
//开启缓存管理
myShiroRealm.setCacheManager(new RedisCacheManager());
myShiroRealm.setCachingEnabled(true);//开启全局缓存
myShiroRealm.setAuthenticationCachingEnabled(true);//认证缓存
myShiroRealm.setAuthenticationCacheName("authorizationCache");
myShiroRealm.setAuthorizationCachingEnabled(true);//开启授权缓存
myShiroRealm.setAuthorizationCacheName("authorizationCache");
return myShiroRealm;
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}
/**
* 注册全局异常处理
* @return
*/
// @Bean(name = "exceptionHandler")
// public HandlerExceptionResolver handlerExceptionResolver() {
// /// return new ExceptionHandler();
// return nulll;
// }
}
3.2 自定义shiroRealm
public class UserRealm extends AuthorizingRealm {
private static Logger LOGGER = LoggerFactory.getLogger(UserRealm.class);
Map<String,String> userMap = new HashMap<>(16);
{
userMap.put("aa","12");
super.setName(getName());
}
private String getPasswordByName(String userName){
return userMap.get(userName);
}
/**
* Shiro登录认证(原理:用户提交 用户名和密码 --- shiro 封装令牌 ---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制 )
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
LOGGER.info("Shiro开始登录认证");
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String username = (String) authcToken.getPrincipal();
// User user = userService.findUserByLoginName(token.getUsername());
User user = new User();
user.setUsername(username);
user.setPassword("12");
user.setId("12");
// 账号不存在
if (user == null) {
return null;
}
// List<Long> roleList = roleService.findRoleIdListByUserId(user.getId());
List<Long> roleList = new ArrayList<Long>();
// roleList.add(Long.parseLong(UserInfoCache.getLoginnamerolecache().get(token.getUsername())));
User shiroUser = new User(user.getId(), user.getUsername(), user.getPassword(), roleList);
// 认证缓存信息
String password = getPasswordByName(username);
System.out.println("username-----"+username);
System.out.println("password-----"+password);
return new SimpleAuthenticationInfo(shiroUser.getUsername(), shiroUser.getPassword(), getName());
}
/**
* Shiro权限认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("s11-----");
User shiroUser = (User) principals.getPrimaryPrincipal();
List<Long> roleList = shiroUser.getRoleList();
Set<String> urlSet = Sets.newHashSet();
for (Long roleId : roleList) {
//List<Map<Long, String>> roleResourceList = roleService.findRoleResourceListByRoleId(roleId);
List<Map<Long, String>> roleResourceList =null;
if (roleResourceList != null) {
for (Map<Long, String> map : roleResourceList) {
//if (StringUtils.isNoneBlank(map.get("URL"))) {
urlSet.add(map.get("URL"));
//}
}
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(urlSet);
return info;
}
}
3.3 登录方法
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model, HttpServletRequest request) {
LOGGER.info("GET请求登录");
if (SecurityUtils.getSubject().isAuthenticated()) {
// return "redirect:/index";
return "index";
}
return "index";
}
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public String initLogin(String name,String passWord) {
String json;
Result result = new Result();
if (StringUtils.isBlank(name)) {
result.setMsg("用户名不能为空");
json = objToStr(result);
return json;
}
if (StringUtils.isBlank(passWord)) {
result.setMsg("密码不能为空");
json = objToStr(result);
return json;
}
// UserInfoCache.getLoginnamerolecache().put(userName, roleId);
Subject user = SecurityUtils.getSubject();
//UsernamePasswordToken token = new UsernamePasswordToken(name, DigestUtils.md5Hex(passWord).toCharArray());
System.out.println("name-----"+name);
System.out.println("passWord-----"+passWord);
UsernamePasswordToken token = new UsernamePasswordToken(name, passWord);
token.setRememberMe(true);
try {
user.login(token);
} catch (UnknownAccountException e) {
LOGGER.error("账号不存在:{}", e);
result.setMsg("账号不存在");
json = objToStr(result);
return json;
} catch (DisabledAccountException e) {
LOGGER.error("账号未启用:{}", e);
result.setMsg("账号未启用");
json = objToStr(result);
return json;
} catch (IncorrectCredentialsException e) {
LOGGER.error("密码错误:{}", e);
result.setMsg("密码错误");
json = objToStr(result);
return json;
} catch (RuntimeException e) {
LOGGER.error("未知错误,请联系管理员:{}", e);
result.setMsg("未知错误,请联系管理员");
json = objToStr(result);
return json;
}
result.setSuccess(true);
json = objToStr(result);
System.out.println("-success---"+json);
return json;
}
四 配置redis缓存(大概的)
4.1 配置文件配置redis
spring:
datasource:
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@localhost:1521:orcl
username: arya
password: arya
type: com.alibaba.druid.pool.DruidDataSource
profiles:
active: abc,elasticSearch
redis:
port: 6379
host: localhost
database: 0
4.2 自定义shiro缓存管理器
package com.msun.config.shiro.redisCache;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
//自定义shiro缓存管理器
public class RedisCacheManager implements CacheManager {
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
return new RedisCache<K, V>();
}
}
4.3 自定义缓存的增删改查
redis模板使用自定义的spring单例
import java.util.Collection;
import java.util.Set;
public class RedisCache<k,v> implements Cache<k,v> {
@Override
public v get(k key) throws CacheException {
RedisTemplate redisTemplate = StringUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
return (v) redisTemplate.opsForValue().get(key.toString());
}
@Override
public v put(k key, v value) throws CacheException {
RedisTemplate redisTemplate = StringUtils.getBean("redisTemplate");
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.opsForValue().set(key.toString(),value);
return value;
}
@Override
public v remove(k key) throws CacheException {
return null;
}
@Override
public void clear() throws CacheException {
}
@Override
public int size() {
return 0;
}
@Override
public Set<k> keys() {
return null;
}
@Override
public Collection<v> values() {
return null;
}
4.4 配置spring是实体类
@Repository
public class SpringUtils implements BeanFactoryPostProcessor {
private static ConfigurableListableBeanFactory beanFactory; // Spring应用上下文环境
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
StringUtils.beanFactory = beanFactory;
}
public static ConfigurableListableBeanFactory getBeanFactory() {
return beanFactory;
}
/**
* 获取对象
*
* @param name
* @return Object 一个以所给名字注册的bean的实例
* @throws org.springframework.beans.BeansException
*
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException {
return (T) getBeanFactory().getBean(name);
}
/**
* 获取类型为requiredType的对象
*
* @param clz
* @return
* @throws org.springframework.beans.BeansException
*
*/
public static <T> T getBean(Class<T> clz) throws BeansException {
T result = (T) getBeanFactory().getBean(clz);
return result;
}
/**
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
*
* @param name
* @return boolean
*/
public static boolean containsBean(String name) {
return getBeanFactory().containsBean(name);
}
/**
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
*
* @param name
* @return boolean
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return getBeanFactory().isSingleton(name);
}
/**
* @param name
* @return Class 注册对象的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return getBeanFactory().getType(name);
}
/**
* 如果给定的bean名字在bean定义中有别名,则返回这些别名
*
* @param name
* @return
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
*
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
return getBeanFactory().getAliases(name);
}
}
4.5 其他具体可参照supervise项目。。。
4.6 结构
1.4 pom.xml文件
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.0.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--JDBC坐标-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.1.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<!-- 不传递依赖-->
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<!-- 通用mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
从配置文件获取内容注入bean
1 新建fastdfs-client.properties文件
fastdfs.clients[0]=febs
fastdfs.connect_timeout_in_seconds=10
2 创建实体类
@Data
@SpringBootConfiguration
@PropertySource(value = {"classpath:fastdfs-client.properties"})
@ConfigurationProperties(prefix = "fastdfs")
public class Do {
private String connect_timeout_in_seconds;
private List<String> clients;
}
3 调用实体类
@Autowired
private Do dos;
System.out.println("---"+dos.getConnect_timeout_in_seconds()+"---lsit--"+dos.getClients());
4 list集合的获取
fastdfs-client.properties
fastdfs.clients[0].name=febs
fastdfs.clients[0].age=febs
新建DoDetail
@Data
public class DoDetail {
private String name;
private String sex;
}
@Data
@SpringBootConfiguration
@PropertySource(value = {"classpath:fastdfs-client.properties"})
@ConfigurationProperties(prefix = "fastdfs")
public class Do {
private List<DoDetail> clients;
}
获取
System.out.println("---lsit--"+dos.getClients().get(0).getName());
pom引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>