在这里,第二次使用springboot开发,看过我之前的文章可知。因为spirngboot是去除xml等繁琐配置,大部分内容都已经帮你设置好,因此需要有一定的spring基础才能学习,不然不明白原理会难以下手。
文档结构图
1. pom.xml需要引入的依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--事务处理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!--断点上传工具-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.1.41</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>-->
</dependency>
<!--undertow服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!--freemarker ftl-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<!--打包时的名字-->
<finalName>webApp</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<!--打包时跳过单元测试类-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
2. application.yml中相关配置
spring:
datasource:
hikari:
username: root
password: ####
driver-class-name: com.mysql.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
max-lifetime: 176500
maximum-pool-size: 15
connection-timeout: 30000
redis:
host: 192.168.110.130
port: 6379
password: ####
timeout: 500 #超时时间
pool:
maxWaitMillis: -1 #连接池最大阻塞等待时间(使用负值表示没有限制)
maxIdle: 8 #最大空闲连接
server:
undertow:
buffer-size: 1024
direct-buffers: true
#DEBUG模式
logging:
level: debug
3. Main主函数入口相关配置
@Configuration
@Controller
@ComponentScan(basePackages = "com.example.demo") //扫描注解
@MapperScan("com.example.demo.dao") //扫描接口
@SpringBootApplication //开启初始化配置,必须有
@EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
@EnableTransactionManagement //开启事务
@EnableCaching //开启缓存
public class DemoApplication {
@Autowired
private UserService userService;
@RequestMapping("/index")
public String index(){
return "index";
}
/*@Bean
public StringHttpMessageConverter stringHttpMessageConverter(){
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(Charset.forName("ISO-8859-1"));
return stringHttpMessageConverter;
}
spring boot默认使用utf-8的消息转发器,这里可以进行覆盖测试
*/
@RequestMapping("/upload")
public @ResponseBody String upload(@RequestParam("files")MultipartFile[] files) throws Exception{
String path = "E:\\upload\\";
for(int i = 0;i<files.length;i++){
if(!files[i].isEmpty()){
String filename = files[i].getOriginalFilename();
String new_filename = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));
File f = new File(path + new_filename);
// System.out.println(f.toString());
files[i].transferTo(f);//sd
}
}
return "up success";
}
@RequestMapping("/download")
public String download(HttpServletResponse response){
String filename = "test.pdf";
response.setHeader("content-type","application/octet-stream");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition","attachment;filename="+filename);
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
os = response.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(new File("E:\\upload\\"+filename)));
int i;
while((i = bis.read(buff)) != -1){
os.write(buff,0,buff.length);
os.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
os.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return "down success";
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4. 自定义Config相关配置
- Hikari配置
@Configuration
public class HikariConfig {
/*如果有其他需求可以在这里配置*/
@Bean
@ConfigurationProperties(prefix = "spring.dataSource.hikari")
public DataSource dataSource(){
HikariDataSource hikariDataSource = new HikariDataSource();
// hikariDataSource.setConnectionTimeout(50000);优先级没有application.yml高
System.out.println("Hikari加载成功");
return hikariDataSource;
}
}
- 拦截器配置
//自定义拦截器,继承WebMvcConfigurerAdapter并且重写addInterceptors方法,然后添加拦截策略
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter{
@Override
public void addInterceptors(InterceptorRegistry registry) {
System.out.println("CustomInterceptor加载成功");
registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/**");
}
}
- 文件上传配置
@Configuration
public class MultipartConfig {
@Bean
public MultipartResolver multipartResolver(){
CustomMultipartResolver resolver = new CustomMultipartResolver();
System.out.println("CustomMultipartResolver加载成功");
resolver.setMaxUploadSize(1024*1024*100);//5MB
return resolver;
}
}
- mybatis配置
@Configuration
public class MybatisConfig {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
System.out.println("SqlSessionFactoryBean加载成功");
return sqlSessionFactoryBean;
}
}
- redis配置
@Configuration
public class RedisConfig extends CachingConfigurerSupport{
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.pool.maxIdle}")
private int maxIdle;
@Value("${spring.redis.pool.maxWaitMillis}")
private int maxWaitMillis;
@Bean
public JedisPool jedisPool(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMinIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
JedisPool jedisPool = new JedisPool(jedisPoolConfig,host,port,timeout,password);
System.out.println("jedis配置完成");
return jedisPool;
}
}
- undertow配置
@Configuration
public class UndertowConfig {
@Bean
@ConfigurationProperties(prefix = "server.undertow")
public UndertowEmbeddedServletContainerFactory undertowEmbeddedServletContainerFactory(){
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
System.out.println("undertow加载成功");
// factory.setPort(8088);
return factory;
}
}
5. 拦截器类
public class CustomInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("拦截在这儿");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
6. 文件断点上传类
- 监听条
@Component
public class FileUpLoadProgressListener implements ProgressListener {
private HttpSession session;
public void setSession(HttpSession session){
this.session = session;
ProgressEntity status = new ProgressEntity();
session.setAttribute("status",status);
}
@Override
public void update(long nowByte, long process, int count) {
ProgressEntity progressEntity = (ProgressEntity) session.getAttribute("status");
progressEntity.setUpByte(nowByte);
progressEntity.setUpSize(process);
progressEntity.setUpItems(count);
System.out.println("装载文件上传内容。。。" + progressEntity);
}
}
- 继承重写
public class CustomMultipartResolver extends CommonsMultipartResolver{
@Autowired
private FileUpLoadProgressListener listener;
@Override
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
listener.setSession(request.getSession());
fileUpload.setProgressListener(listener);
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems,encoding);
} catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
}
catch (FileUploadBase.FileSizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex);
}
catch (FileUploadException ex) {
throw new MultipartException("Failed to parse multipart servlet request", ex);
}
}
}
7. 自定义全局异常类
@ControllerAdvice
public class GlobalException {
@ExceptionHandler(Exception.class)
@ResponseBody
public Map<String,Object> exceptionHandler(Model model){
HashMap<String, Object> result = new HashMap<>();
result.put("code",500);
result.put("message","亲,系统错误请稍后重试...");
//返回json格式
return result;
}
}
8. dao层配置
- mybatis
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user")
public List<User> selectAll();
}
- redis
@Repository
public class RedisClient {
@Autowired
private JedisPool jedisPool;
public void addJsonData(String key,String target){
jedisPool.getResource().set(key,target);
}
public boolean isExistKey(String key){
Boolean result = jedisPool.getResource().exists(key);
return result;
}
}
9. 实体类配置
- ProgressEntity
//涉及流,需要序列化
public class ProgressEntity implements Serializable{
private long upByte = 0L;
private long upSize = 0L;
private int upItems;
@Override
public String toString() {
return "ProgressEntity{" +
"upByte=" + upByte +
", upSize=" + upSize +
", upItems=" + upItems +
'}';
}
public long getUpByte() {
return upByte;
}
public void setUpByte(long upByte) {
this.upByte = upByte;
}
public long getUpSize() {
return upSize;
}
public void setUpSize(long upSize) {
this.upSize = upSize;
}
public int getUpItems() {
return upItems;
}
public void setUpItems(int upItems) {
this.upItems = upItems;
}
}
- User
public class User implements Serializable{
private int id;
private String userName;
private String address;
private Date date;
@Override
public String toString() {
return "User{" +
"id=" + id +
", userName='" + userName + '\'' +
", address='" + address + '\'' +
", date=" + date +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
10. service层配置
@Service
//@Transactional //这个注解可以加在类和方法,方法上说明此方法使用事务
public class UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RedisClient redisClient;
/*测试redis缓存*/
@Transactional(propagation = Propagation.SUPPORTS)
@Cacheable(value = "getAllUsers") //在getAllUsers找缓存
public List<User> getAllUsers(){
System.out.println("如果第二次没有打印,说明缓存存在");
return userMapper.selectAll();
}
@Transactional(propagation = Propagation.REQUIRED)
@CacheEvict(value = "getAllUsers")//CacheEvict去除缓存,CachePut加入缓存
public void flushAllUsers(){
}
@Transactional(propagation = Propagation.REQUIRED)
public void addJson(String key,String target){
redisClient.addJsonData(key,target);
}
}
11. 测试结果
- 访问index
- 断点上传
- 下载