SpringBoot Starter设计

SpringBoot重要组件是各种Starter,需要定制扩展SpringBoot功能,必须自定义Starter。本例自定义Starter只使用与SpringBoot 2.x以后版本,实现Redis缓存管理,文件上传基本服务,使用JDBC操作数据库。

定义Maven工程,定义POM依赖

<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.gufang</groupId>
  <artifactId>mystarter-spring-boot-starter</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mystarter-spring-boot-starter</name>
  <url>http://maven.apache.org</url>


	<properties>
		<!-- project -->
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>

		<!-- dependencies -->
		<spring-boot.version>1.5.10.RELEASE</spring-boot.version>

		<!-- plugins -->
		<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
		<maven-surefire-plugin.version>2.20.1</maven-surefire-plugin.version>
		<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
		<maven-javadoc-plugin.version>3.0.0</maven-javadoc-plugin.version>
		<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
		    <groupId>redis.clients</groupId>
		    <artifactId>jedis</artifactId>
		    <version>2.9.0</version>
		</dependency>
		<dependency>
		    <groupId>com.alibaba</groupId>
		    <artifactId>fastjson</artifactId>
		    <version>1.2.54</version>
		</dependency>
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-databind</artifactId>
		    <version>2.9.8</version>
		</dependency>
		<dependency>
		    <groupId>com.fasterxml.jackson.core</groupId>
		    <artifactId>jackson-annotations</artifactId>
		    <version>2.9.0</version>
		</dependency>
		<dependency>
		    <groupId>org.springframework.data</groupId>
		    <artifactId>spring-data-redis</artifactId>
		    <version>2.1.6.RELEASE</version>
		</dependency>
		<dependency>
		    <groupId>org.springframework</groupId>
		    <artifactId>spring-web</artifactId>
		    <version>5.1.6.RELEASE</version>
		</dependency>
		<dependency>
		    <groupId>javax.servlet</groupId>
		    <artifactId>javax.servlet-api</artifactId>
		    <version>4.0.0</version>
		    <scope>provided</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>${spring-boot.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>${maven-compiler-plugin.version}</version>
				<configuration>
					<encoding>${project.build.sourceEncoding}</encoding>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

定义配置文件操作类

本例重用了SpringBoot-data-jdbc-starter配置信息

package com.gufang;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;


@ConfigurationProperties(prefix="spring.datasource")
public class MyStarterProperties {
	private String driverClassName = null;
	private String url = null;
	private String username = null;
	private String password = null;
	
	private String redishost=null;
	private String redisport=null;

	public String getDriverClassName() {
		return driverClassName;
	}
	public void setDriverClassName(String driverClassName) {
		this.driverClassName = driverClassName;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getRedishost() {
		return redishost;
	}
	public void setRedishost(String redishost) {
		this.redishost = redishost;
	}
	public String getRedisport() {
		return redisport;
	}
	public void setRedisport(String redisport) {
		this.redisport = redisport;
	}

}

使能注解

package com.gufang;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableMyStarterConfiguration {

}

自配置类

package com.gufang;

import java.time.Duration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;


@Configuration //向Spring容器配置对象
@ConditionalOnBean(annotation=EnableMyStarterConfiguration.class)
//当Spring容器中包含EnableMyStarterConfiguration声明对象时,进行配置MyStarterAutoConfiguration
@EnableConfigurationProperties(MyStarterProperties.class)
@ServletComponentScan
@EnableCaching
public class MyStarterAutoConfiguration {
	@Autowired
	private MyStarterProperties prop;
	
	@Bean
	public MyConnection createConnecton()
	{
		String className=prop.getDriverClassName();
		String user=prop.getUsername();
		String pwd=prop.getPassword();
		String url=prop.getUrl();
		String redishost=prop.getRedishost();
		String redisport=prop.getRedisport();
		return new MyConnection(className,url,user,pwd,redishost,redisport);
	}
	
	/**
	* 生成Redis的键值,根据类名+方法名+参数值的形式
	* @return
	*/
    @Bean(name = "keyGenerator")
    public KeyGenerator keyGenerator() {
        return new KeyGenerator(){
            @Override
            public Object generate(Object target, java.lang.reflect.Method method, 
                    Object... params) {
                StringBuffer sb = new StringBuffer();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for(Object obj:params){
                    if(obj != null)
                    {
                    	sb.append("_");
                        sb.append(obj.toString());
                    }
                }
                return sb.toString();
            }
        };
    }
    

    @SuppressWarnings("rawtypes")
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    	// 设置缓存有效期
    	RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
    				.entryTtl(Duration.ofSeconds(100000000000L));
    	return RedisCacheManager
    	.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
    	.cacheDefaults(redisCacheConfiguration).build();

    }

    @Bean
    @SuppressWarnings({"rawtypes", "unchecked"})
    public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory connectionFactory){
        RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<Object,Object>();
        redisTemplate.setConnectionFactory(connectionFactory);
        //使用Jackson2JsonRedisSerializer替换默认的序列化规则
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper=new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);


        //设置value的序列化规则
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        //设置key的序列化规则
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    
  
//	/**
//	 * 生成CacheManager对象
//	* @param redisTemplate
//	* @return
//	*/
//	  @Bean 
//	  public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
//	      RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//	      cacheManager.setDefaultExpiration(10000);
//	      return cacheManager;
//	  }
//	
//		/**
//	 * 生成Redis内存管理模板,注解@Primary代表此对象是同类型对象的主对象,优先被使用
//	* @param factory
//	* @return
//	*/
//	  @Primary
//	  @Bean
//	  public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
//	      RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
//	      template.setKeySerializer(new StringRedisSerializer());
//	      template.setConnectionFactory(factory);
//	      setSerializer(template);
//	      template.afterPropertiesSet();
//	      return template;
//	  }

	/**
	 * 序列化Redis的键和值对象
	* @param template
	*/
    private void setSerializer(RedisTemplate template){
        @SuppressWarnings({ "rawtypes", "unchecked" })
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = 
            new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
     }
    
    @Bean
    public MyRedisTool createRedisTool()
    {
    	return new MyRedisTool();
    }
    
    @Bean
    public MyFileTool createFileTool()
    {
    	return new MyFileTool();
    }
}

数据库操作类

package com.gufang;

import java.sql.Statement;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.gufang.model.FileInfo;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class MyConnection {
	private String className,url,user,pwd,redishost,redisport = null;
	
	public MyConnection(String className,String url,String user,String pwd,
			String redishost,String redisport)
	{
		this.className= className;
		this.url= url;
		this.user= user;
		this.pwd= pwd;
		this.redishost=redishost;
		this.redisport=redisport;
		
		//检查数据库表T_FILE是否存在
		createFileTable();
	}
	
	public Connection getConnection()
	{
		try {
			Class.forName(className);
			return DriverManager.getConnection(url, user, pwd);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public List<Map> query(String sql)
	{
		try {
			Connection conn=getConnection();
			Statement statement=conn.createStatement();
			ResultSet rs=statement.executeQuery(sql);
			java.sql.ResultSetMetaData rsmData=rs.getMetaData();
			List<Map> lst=new ArrayList<Map>();
			while(rs.next())//结果集指针
			{
				int cols=rsmData.getColumnCount();
				Map map=new HashMap();
				for(int i=1;i<=cols;i++)
				{
					String colName=rsmData.getColumnName(i);
					String val=rs.getString(colName);
					map.put(colName, val);
				}
				lst.add(map);
			}
			rs.close();
			statement.close();
			conn.close();
			return lst;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private void createFileTable()
	{
		try {
			Connection conn=getConnection();
			Statement statement=conn.createStatement();
			String checkSql = "select id from T_FILE";
			try {
				statement.execute(checkSql);
				System.out.println("######################################################");
				System.out.println("###数据库表    T_FILE已经存在                                                                                          ###");
				System.out.println("######################################################");
			} catch (Exception e) {
				String createSql = "create table T_FILE(id long,"+
						"name varchar(200),contexttype varchar(100),length bigint,dt date,content mediumblob)";
				statement.execute(createSql);
				System.out.println("######################################################");
				System.out.println("###数据库表    T_FILE被创建                                                                                              ###");
				System.out.println("######################################################");
			}
			statement.close();
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void saveFileInfo(FileInfo fi)
	{
		try {
			Connection conn=getConnection();
			String sql = "insert into T_FILE(id,name,contexttype,length,dt,content)"+
					"values(?,?,?,?,?,?)";
			PreparedStatement pstat = conn.prepareStatement(sql);
			long id = System.currentTimeMillis();
			fi.setId(id);
			pstat.setLong(1, fi.getId());
			pstat.setString(2, fi.getName());
			pstat.setString(3, fi.getContextType());
			pstat.setLong(4, fi.getLength());
			pstat.setDate(5, new Date(System.currentTimeMillis()));
			
			Blob blob = conn.createBlob();
			OutputStream out = blob.setBinaryStream(1); 
			out.write(fi.getContent());
			out.close();
			pstat.setBlob(6, blob); 
			
			pstat.executeUpdate();
			pstat.close();
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public FileInfo getFileInfoById(Long id)
	{
		try {
			FileInfo fi = new FileInfo();
			Connection conn=getConnection();
			String sql = "select * from T_FILE where id=?";
			PreparedStatement pstat = conn.prepareStatement(sql);
			pstat.setLong(1, id);
			ResultSet rs = pstat.executeQuery();
			if(rs.next())
			{
				fi.setId(id);
				fi.setName(rs.getString("name"));
				fi.setContextType(rs.getString("contexttype"));
				fi.setDt(rs.getDate("dt"));
				fi.setLength(rs.getLong("length"));
				Blob blob = rs.getBlob("content") ;
				InputStream input = blob.getBinaryStream();
				byte[] data = new byte[1024];
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				int pos = 0;
				while((pos=input.read(data))!=-1)
					baos.write(data,0,pos);
				fi.setContent(baos.toByteArray());
			}
			pstat.close();
			conn.close();
			return fi;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}

文件操作类

package com.gufang;

import java.io.InputStream;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.gufang.model.FileInfo;


public class MyFileTool {
	@Autowired
	private MyConnection conn;
	
	public FileInfo uploadFile(HttpServletRequest req)
	{
		if(!(req instanceof MultipartHttpServletRequest))
			return null;
		MultipartHttpServletRequest mreq = (MultipartHttpServletRequest)req;
		MultipartFile multipartFile = mreq.getFile("file");
		try
		{
			InputStream is = multipartFile.getInputStream();
			byte[] bytes = FileCopyUtils.copyToByteArray(is);
			FileInfo fi = new FileInfo();
			fi.setName(multipartFile.getName());
			fi.setContextType(multipartFile.getContentType());
			fi.setLength(new Long(multipartFile.getBytes().length));
			fi.setContent(bytes);
			conn.saveFileInfo(fi);
			return fi;
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}
}

其他类通过源码下载
https://pan.baidu.com/s/1BUs_3qT1XaS64Y3w3iCZRg

项目中使用自定义Starter

通过注解方式使用Redis

在这里插入图片描述
修改Application.properties配置文件
spring.redis.database=0
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
#spring.redis.timeout=0

在这里插入图片描述
在这里插入图片描述

文件上传

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了189 篇原创文章 · 获赞 34 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qixiang_chen/article/details/100025233