├── src
├── main
│ ├── resources
│ │ ├── application.yml
│ │ ├── static
│ │ │ ├── favicon.ico
│ │ │ └── image
│ │ │ │ └── template.png
│ │ ├── application-prod.yml
│ │ ├── application-test.yml
│ │ ├── templates
│ │ │ ├── error.html
│ │ │ └── fremarkertemp.html
│ │ ├── public
│ │ │ └── index.html
│ │ ├── log4j2-prod.xml
│ │ ├── log4j2-test.xml
│ │ ├── application-dev.yml
│ │ └── log4j2-dev.xml
│ └── java
│ │ └── com
│ │ └── zimug
│ │ └── bootlaunch
│ │ ├── model
│ │ ├── Reader.java
│ │ ├── Address.java
│ │ ├── Person.java
│ │ └── ArticleVO.java
│ │ ├── config
│ │ ├── exception
│ │ │ ├── ModelView.java
│ │ │ ├── CustomExceptionType.java
│ │ │ ├── CustomException.java
│ │ │ ├── ModelViewException.java
│ │ │ ├── ModelViewAspect.java
│ │ │ ├── AjaxResponse.java
│ │ │ └── WebExceptionHandler.java
│ │ ├── DozerBeanMapperConfigure.java
│ │ ├── accesslog
│ │ │ ├── AccessLog.java
│ │ │ └── AccessLogInterceptor.java
│ │ ├── MyWebMvcConfigurer.java
│ │ ├── Swagger2.java
│ │ └── RedisConfig.java
│ │ ├── dao
│ │ └── PersonRepository.java
│ │ ├── service
│ │ ├── ArticleRestService.java
│ │ ├── ExceptionService.java
│ │ └── ArticleMybatisRestServiceImpl.java
│ │ ├── BootLaunchApplication.java
│ │ ├── controller
│ │ ├── LogDemoController.java
│ │ ├── RedisSessionController.java
│ │ ├── TemplateController.java
│ │ ├── HelloController.java
│ │ ├── FastdfsController.java
│ │ └── ArticleRestController.java
│ │ ├── utils
│ │ ├── DozerUtils.java
│ │ └── AdrressIpUtils.java
│ │ └── generator
│ │ └── testdb
│ │ ├── ArticleMapper.java
│ │ ├── Article.java
│ │ ├── ArticleMapper.xml
│ │ └── ArticleExample.java
└── test
│ └── java
│ └── com
│ └── zimug
│ └── bootlaunch
│ ├── BootLaunchApplicationTests.java
│ ├── mybatis
│ └── MybatisTest.java
│ ├── redis
│ ├── RedisRepositoryTest.java
│ └── RedisConfigTest.java
│ └── restful
│ ├── ArticleRestControllerTest.java
│ ├── ArticleRestControllerTest2.java
│ └── ArticleRestControllerTest3.java
├── .gitignore
├── README.md
└── pom.xml
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | #需要使用的配置文件
2 | spring:
3 | profiles:
4 | active: dev
--------------------------------------------------------------------------------
/src/main/resources/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hanxt/boot-launch/HEAD/src/main/resources/static/favicon.ico
--------------------------------------------------------------------------------
/src/main/resources/static/image/template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hanxt/boot-launch/HEAD/src/main/resources/static/image/template.png
--------------------------------------------------------------------------------
/src/main/resources/application-prod.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8889
3 |
4 |
5 | spring:
6 | jackson:
7 | date-format: yyyy-MM-dd HH:mm:ss
8 | time-zone: GMT+8
9 |
10 | logging:
11 | config: classpath:log4j2-prod.xml
--------------------------------------------------------------------------------
/src/main/resources/application-test.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8890
3 |
4 |
5 | spring:
6 | jackson:
7 | date-format: yyyy-MM-dd HH:mm:ss
8 | time-zone: GMT+8
9 |
10 |
11 | logging:
12 | config: classpath:log4j2-prod.xml
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/model/Reader.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.model;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class Reader {
7 |
8 | private String name;
9 |
10 | private int age;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/resources/templates/error.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | error.html
6 |
7 |
8 | error
9 |
10 | ${exception}
11 | ${url}
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/exception/ModelView.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.exception;
2 |
3 | import java.lang.annotation.*;
4 |
5 | @Documented
6 | @Retention(RetentionPolicy.RUNTIME)
7 | @Target({ElementType.METHOD})//只能在方法上使用此注解
8 | public @interface ModelView {
9 |
10 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/dao/PersonRepository.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.dao;
2 |
3 | import com.zimug.bootlaunch.model.Person;
4 | import org.springframework.data.repository.CrudRepository;
5 |
6 | public interface PersonRepository extends CrudRepository {
7 | // 继承CrudRepository,获取基本的CRUD操作
8 | }
--------------------------------------------------------------------------------
/src/main/resources/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 首页
6 |
7 |
8 | 首页
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/model/Address.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.model;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 | @Data
8 | public class Address implements Serializable {
9 |
10 | private static final long serialVersionUID = -8985545025228238771L;
11 |
12 | String city;
13 | String country;
14 |
15 | public Address(String city, String country) {
16 | this.city = city;
17 | this.country = country;
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/service/ArticleRestService.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.service;
2 |
3 | import com.zimug.bootlaunch.model.ArticleVO;
4 |
5 | import java.util.List;
6 |
7 | public interface ArticleRestService {
8 |
9 | ArticleVO saveArticle(ArticleVO article);
10 |
11 | void deleteArticle(Long id);
12 |
13 | ArticleVO updateArticle(ArticleVO article);
14 |
15 | ArticleVO getArticle(Long id);
16 |
17 | List getAll();
18 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/DozerBeanMapperConfigure.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config;
2 |
3 | import org.dozer.DozerBeanMapper;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 | @Configuration
8 | public class DozerBeanMapperConfigure {
9 | @Bean
10 | public DozerBeanMapper mapper() {
11 | DozerBeanMapper mapper = new DozerBeanMapper();
12 | return mapper;
13 | }
14 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 |
30 | ### VS Code ###
31 | .vscode/
32 |
33 |
34 | logs/
35 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/accesslog/AccessLog.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.accesslog;
2 |
3 | import lombok.Data;
4 |
5 | import java.util.Date;
6 |
7 | @Data
8 | public class AccessLog {
9 | //访问者用户名
10 | private String username;
11 | //请求路径
12 | private String url;
13 | //请求消耗时长
14 | private Integer duration;
15 | //http 方法:GET、POST等
16 | private String httpMethod;
17 | //http 请求响应状态码
18 | private Integer httpStatus;
19 | //访问者ip
20 | private String ip;
21 | //此条记录的创建时间
22 | private Date createTime;
23 | }
--------------------------------------------------------------------------------
/src/main/resources/templates/fremarkertemp.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | freemarker简单示例
6 |
7 |
8 | Hello Freemarker
9 |
10 |
11 |
12 | | 作者 |
13 | 教程名称 |
14 | 内容 |
15 |
16 |
17 | <#list articles as article>
18 |
19 | | ${article.author} |
20 | ${article.title} |
21 | ${article.content} |
22 |
23 | #list>
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/BootLaunchApplication.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch;
2 |
3 | import org.mybatis.spring.annotation.MapperScan;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.cache.annotation.EnableCaching;
7 |
8 | @SpringBootApplication
9 | @MapperScan(basePackages = {"com.zimug.bootlaunch.generator"})
10 | @EnableCaching
11 | public class BootLaunchApplication {
12 |
13 | public static void main(String[] args) {
14 | SpringApplication.run(BootLaunchApplication.class, args);
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/java/com/zimug/bootlaunch/BootLaunchApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
7 | import org.springframework.test.context.junit4.SpringRunner;
8 |
9 | @RunWith(SpringRunner.class)
10 | @SpringBootTest
11 | @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 30 * 60 * 1000)
12 | public class BootLaunchApplicationTests {
13 |
14 | @Test
15 | public void contextLoads() {
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/exception/CustomExceptionType.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.exception;
2 |
3 | public enum CustomExceptionType {
4 | USER_INPUT_ERROR(400,"用户输入异常"),
5 | SYSTEM_ERROR (500,"系统服务异常"),
6 | OTHER_ERROR(999,"其他未知异常");
7 |
8 | CustomExceptionType(int code, String typeDesc) {
9 | this.code = code;
10 | this.typeDesc = typeDesc;
11 | }
12 |
13 | private String typeDesc;//异常类型中文描述
14 |
15 | private int code; //code
16 |
17 | public String getTypeDesc() {
18 | return typeDesc;
19 | }
20 |
21 | public int getCode() {
22 | return code;
23 | }
24 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/exception/CustomException.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.exception;
2 |
3 | public class CustomException extends RuntimeException {
4 | //异常错误编码
5 | private int code ;
6 | //异常信息
7 | private String message;
8 |
9 | private CustomException(){}
10 |
11 | public CustomException(CustomExceptionType exceptionTypeEnum, String message) {
12 | this.code = exceptionTypeEnum.getCode();
13 | this.message = message;
14 | }
15 |
16 | public int getCode() {
17 | return code;
18 | }
19 |
20 | @Override
21 | public String getMessage() {
22 | return message;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/model/Person.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.model;
2 |
3 | import lombok.Data;
4 | import org.springframework.data.annotation.Id;
5 | import org.springframework.data.redis.core.RedisHash;
6 |
7 |
8 | import java.io.Serializable;
9 |
10 | @Data
11 | @RedisHash("people")
12 | public class Person implements Serializable {
13 |
14 | private static final long serialVersionUID = -8985545025228238754L;
15 |
16 | @Id
17 | String id;
18 | String firstname;
19 | String lastname;
20 | Address address;
21 |
22 | public Person(String firstname, String lastname) {
23 | this.firstname = firstname;
24 | this.lastname = lastname;
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/controller/LogDemoController.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.controller;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | @RestController
8 | @Slf4j
9 | public class LogDemoController {
10 | //private static Logger log= LoggerFactory.getLogger(LogDemo.class);
11 |
12 | @GetMapping("/logdemo")
13 | public String log(){
14 | log.trace("======trace");
15 | log.debug("======debug");
16 | log.info("======info");
17 | log.warn("======warn");
18 | log.error("======error");
19 | return "logok";
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/exception/ModelViewException.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.exception;
2 |
3 | public class ModelViewException extends RuntimeException{
4 |
5 | //异常错误编码
6 | private int code ;
7 | //异常信息
8 | private String message;
9 |
10 | public static ModelViewException transfer(CustomException e) {
11 | return new ModelViewException(e.getCode(),e.getMessage());
12 | }
13 |
14 | private ModelViewException(int code, String message){
15 | this.code = code;
16 | this.message = message;
17 | }
18 |
19 | int getCode() {
20 | return code;
21 | }
22 |
23 | @Override
24 | public String getMessage() {
25 | return message;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/MyWebMvcConfigurer.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config;
2 |
3 | import com.zimug.bootlaunch.config.accesslog.AccessLogInterceptor;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
7 |
8 | @Configuration
9 | public class MyWebMvcConfigurer implements WebMvcConfigurer {
10 |
11 | //设置排除路径,spring boot 2.*,注意排除掉静态资源的路径,不然静态资源无法访问
12 | private final String[] excludePath = {"/static"};
13 |
14 | @Override
15 | public void addInterceptors(InterceptorRegistry registry) {
16 | registry.addInterceptor(new AccessLogInterceptor()).addPathPatterns("/**").excludePathPatterns(excludePath);
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/utils/DozerUtils.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.utils;
2 |
3 | import com.google.common.collect.Lists;
4 | import org.dozer.DozerBeanMapper;
5 |
6 | import java.util.Collection;
7 | import java.util.Iterator;
8 | import java.util.List;
9 |
10 | public class DozerUtils {
11 |
12 | static DozerBeanMapper dozerBeanMapper = new DozerBeanMapper();
13 |
14 | public static List mapList(Collection sourceList, Class destinationClass){
15 | List destinationList = Lists.newArrayList();
16 | for (Iterator i$ = sourceList.iterator(); i$.hasNext();){
17 | Object sourceObject = i$.next();
18 | Object destinationObject = dozerBeanMapper.map(sourceObject, destinationClass);
19 | destinationList.add(destinationObject);
20 | }
21 | return destinationList;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/controller/RedisSessionController.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.controller;
2 |
3 |
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RequestMethod;
6 | import org.springframework.web.bind.annotation.ResponseBody;
7 | import org.springframework.web.bind.annotation.RestController;
8 |
9 | import javax.servlet.http.HttpSession;
10 | import java.util.UUID;
11 |
12 | @RestController
13 | public class RedisSessionController {
14 |
15 | @RequestMapping(value="/uid",method = RequestMethod.GET)
16 | public @ResponseBody
17 | String uid(HttpSession session) {
18 | UUID uid = (UUID) session.getAttribute("uid");
19 | if (uid == null) {
20 | uid = UUID.randomUUID();
21 | }
22 | session.setAttribute("uid", uid);
23 | return session.getId();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/exception/ModelViewAspect.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.exception;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.aspectj.lang.annotation.AfterThrowing;
5 | import org.aspectj.lang.annotation.Aspect;
6 | import org.aspectj.lang.annotation.Pointcut;
7 | import org.springframework.stereotype.Component;
8 |
9 | @Aspect
10 | @Component
11 | public class ModelViewAspect {
12 |
13 | //设置切入点:这里直接拦截被@ModelView注解的方法
14 | @Pointcut("@annotation(com.zimug.bootlaunch.config.exception.ModelView)")
15 | public void pointcut() { }
16 |
17 | /**
18 | * 当有ModelView的注解的方法抛出异常的时候,做如下的处理
19 | */
20 | @AfterThrowing(pointcut="pointcut()",throwing="e")
21 | public void afterThrowable(Throwable e) {
22 |
23 | if(e instanceof CustomException){
24 | throw ModelViewException.transfer((CustomException) e);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/model/ArticleVO.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.model;
2 |
3 |
4 | import com.fasterxml.jackson.annotation.*;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | import javax.validation.constraints.NotEmpty;
11 | import java.util.Date;
12 | import java.util.List;
13 |
14 | @Data
15 | @AllArgsConstructor
16 | @NoArgsConstructor
17 | @Builder
18 | @JsonPropertyOrder(value={"content","title"})
19 | public class ArticleVO {
20 |
21 | //@JsonIgnore
22 | private Long id;
23 |
24 | @JsonProperty("auther")
25 | private String author;
26 | private String title;
27 | @NotEmpty(message = "文章内容不能为空,请检查您的输入")
28 | private String content;
29 |
30 | @JsonInclude(JsonInclude.Include.NON_NULL)
31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
32 | private Date createTime;
33 | private List reader;
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/generator/testdb/ArticleMapper.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.generator.testdb;
2 |
3 | import com.zimug.bootlaunch.generator.testdb.Article;
4 | import com.zimug.bootlaunch.generator.testdb.ArticleExample;
5 | import java.util.List;
6 | import org.apache.ibatis.annotations.Param;
7 |
8 | public interface ArticleMapper {
9 | long countByExample(ArticleExample example);
10 |
11 | int deleteByExample(ArticleExample example);
12 |
13 | int deleteByPrimaryKey(Long id);
14 |
15 | int insert(Article record);
16 |
17 | int insertSelective(Article record);
18 |
19 | List selectByExample(ArticleExample example);
20 |
21 | Article selectByPrimaryKey(Long id);
22 |
23 | int updateByExampleSelective(@Param("record") Article record, @Param("example") ArticleExample example);
24 |
25 | int updateByExample(@Param("record") Article record, @Param("example") ArticleExample example);
26 |
27 | int updateByPrimaryKeySelective(Article record);
28 |
29 | int updateByPrimaryKey(Article record);
30 | }
--------------------------------------------------------------------------------
/src/test/java/com/zimug/bootlaunch/mybatis/MybatisTest.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.mybatis;
2 |
3 | import com.github.pagehelper.PageHelper;
4 | import com.github.pagehelper.PageInfo;
5 | import com.zimug.bootlaunch.generator.testdb.Article;
6 | import com.zimug.bootlaunch.generator.testdb.ArticleMapper;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.springframework.boot.test.context.SpringBootTest;
10 | import org.springframework.test.context.junit4.SpringRunner;
11 |
12 | import javax.annotation.Resource;
13 | import java.util.List;
14 |
15 | @RunWith(SpringRunner.class)
16 | @SpringBootTest
17 | public class MybatisTest {
18 |
19 | @Resource
20 | ArticleMapper articleMapper;
21 |
22 | @Test
23 | public void testPageHelper(){
24 | // 只有紧跟在PageHelper.startPage方法后的第一个Mybatis的查询(Select)方法会被分页!!!!
25 | PageHelper.startPage(1, 2);
26 | List articles = articleMapper.selectByExample(null);
27 | PageInfo page = PageInfo.of(articles);
28 | System.out.println(page);
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/service/ExceptionService.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.service;
2 |
3 | import com.zimug.bootlaunch.config.exception.CustomException;
4 | import com.zimug.bootlaunch.config.exception.CustomExceptionType;
5 | import org.springframework.stereotype.Service;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | @Service
11 | public class ExceptionService {
12 |
13 | //服务层,模拟系统异常
14 | public void systemBizError() throws CustomException {
15 | try {
16 | Class.forName("com.mysql.jdbc.xxxx.Driver");
17 | } catch (ClassNotFoundException e) {
18 | throw new CustomException(CustomExceptionType.SYSTEM_ERROR,"在XXX业务,myBiz()方法内,出现ClassNotFoundException");
19 | }
20 | }
21 |
22 | //服务层,模拟用户输入数据导致的校验异常
23 | public List userBizError(int input) throws CustomException {
24 | if(input < 0){ //模拟业务校验失败逻辑
25 | throw new CustomException(CustomExceptionType.USER_INPUT_ERROR,"您输入的数据不符合业务逻辑,请确认后重新输入!");
26 | }else{ //
27 | List list = new ArrayList<>();
28 | list.add("科比");
29 | list.add("詹姆斯");
30 | list.add("库里");
31 | return list;
32 | }
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/Swagger2.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import springfox.documentation.builders.ApiInfoBuilder;
6 | import springfox.documentation.builders.PathSelectors;
7 | import springfox.documentation.builders.RequestHandlerSelectors;
8 | import springfox.documentation.service.ApiInfo;
9 | import springfox.documentation.spi.DocumentationType;
10 | import springfox.documentation.spring.web.plugins.Docket;
11 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
12 |
13 | @Configuration
14 | @EnableSwagger2
15 | public class Swagger2 {
16 |
17 | @Bean
18 | public Docket createRestApi() {
19 | return new Docket(DocumentationType.SWAGGER_2)
20 | .apiInfo(apiInfo())
21 | .select()
22 | .apis(RequestHandlerSelectors.basePackage("com.zimug.bootlaunch"))
23 | .paths(PathSelectors.regex("/rest/.*"))
24 | .build();
25 | }
26 |
27 | private ApiInfo apiInfo() {
28 | return new ApiInfoBuilder()
29 | .title("springboot利用swagger构建api文档")
30 | .description("简单优雅的restfun风格")
31 | .termsOfServiceUrl("http://www.zimug.com")
32 | .version("1.0")
33 | .build();
34 | }
35 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/controller/TemplateController.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.controller;
2 |
3 | import com.zimug.bootlaunch.config.exception.ModelView;
4 | import com.zimug.bootlaunch.model.ArticleVO;
5 | import com.zimug.bootlaunch.service.ArticleRestService;
6 | import com.zimug.bootlaunch.service.ExceptionService;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.ui.Model;
9 | import org.springframework.web.bind.annotation.GetMapping;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 |
12 | import javax.annotation.Resource;
13 | import java.util.List;
14 |
15 | @Controller
16 | @RequestMapping("/template")
17 | public class TemplateController {
18 |
19 | @Resource(name="articleMybatisRestServiceImpl")
20 | ArticleRestService articleRestService;
21 |
22 | @Resource
23 | ExceptionService exceptionService;
24 |
25 | @ModelView
26 | @GetMapping("/freemarker")
27 | public String index(Model model) {
28 |
29 | List articles = articleRestService.getAll();
30 |
31 | model.addAttribute("articles", articles);
32 | exceptionService.systemBizError();
33 |
34 | //模版名称,实际的目录为:resources/templates/fremarkertemp.html
35 | return "fremarkertemp";
36 | }
37 | }
--------------------------------------------------------------------------------
/src/test/java/com/zimug/bootlaunch/redis/RedisRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.redis;
2 |
3 | import com.zimug.bootlaunch.dao.PersonRepository;
4 | import com.zimug.bootlaunch.model.Address;
5 | import com.zimug.bootlaunch.model.Person;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.boot.test.context.SpringBootTest;
10 | import org.springframework.test.context.junit4.SpringRunner;
11 |
12 | import java.util.Optional;
13 |
14 | @RunWith(SpringRunner.class)
15 | @SpringBootTest
16 | public class RedisRepositoryTest {
17 |
18 | @Autowired
19 | PersonRepository personRepository;
20 |
21 | @Test
22 | public void test(){
23 |
24 | Person rand = new Person("kobe", "byrant");
25 | rand.setAddress(new Address("luosanji", "USA"));
26 | personRepository.save(rand);
27 | Optional op = personRepository.findById(rand.getId());
28 | Person p2 = op.get();
29 | personRepository.count();
30 | //personRepository.delete(rand);
31 |
32 | }
33 |
34 | @Test
35 | public void testDelete(){
36 |
37 |
38 | personRepository.deleteById("24bda079-619f-438e-a8c8-cfc3f1aab487");
39 |
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/src/main/resources/log4j2-prod.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/main/resources/log4j2-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/controller/HelloController.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.controller;
2 |
3 | import com.zimug.bootlaunch.config.exception.AjaxResponse;
4 | import com.zimug.bootlaunch.model.ArticleVO;
5 | import com.zimug.bootlaunch.service.ExceptionService;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.ResponseBody;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | import javax.annotation.Resource;
12 |
13 | @Slf4j
14 | @RestController
15 | public class HelloController {
16 |
17 | @Resource
18 | ExceptionService exceptionService;
19 |
20 | //private static final Logger log = LoggerFactory.getLogger(HelloController.class);
21 |
22 | @RequestMapping("/hello")
23 | public ArticleVO hello() {
24 | /*ArticleRestService article = new ArticleRestService(1L,"zimug");
25 |
26 | article.setAuthor("字母哥");*/
27 |
28 | ArticleVO article1 = ArticleVO.builder().id(3L).author("莫言").build();
29 |
30 | log.info("测试一下" + article1);
31 |
32 | return article1;
33 | }
34 |
35 |
36 |
37 | @RequestMapping("/ex/system")
38 | public @ResponseBody AjaxResponse system() {
39 |
40 | exceptionService.systemBizError();
41 |
42 | return AjaxResponse.success();
43 | }
44 |
45 |
46 | @RequestMapping("/ex/user")
47 | public @ResponseBody AjaxResponse user(Integer input) {
48 |
49 | return AjaxResponse.success(exceptionService.userBizError(input));
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/exception/AjaxResponse.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.exception;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class AjaxResponse {
7 |
8 |
9 | private boolean isok;
10 | private int code;
11 | private String message;
12 | private Object data;
13 |
14 | private AjaxResponse() {
15 |
16 | }
17 |
18 | //请求出现异常时的响应数据封装
19 | public static AjaxResponse error(CustomException e) {
20 |
21 | AjaxResponse resultBean = new AjaxResponse();
22 | resultBean.setIsok(false);
23 | resultBean.setCode(e.getCode());
24 | if(e.getCode() == CustomExceptionType.USER_INPUT_ERROR.getCode()){
25 | resultBean.setMessage(e.getMessage());
26 | }else if(e.getCode() == CustomExceptionType.SYSTEM_ERROR.getCode()){
27 | resultBean.setMessage(e.getMessage() + ",系统出现异常,请联系管理员电话:1375610xxxx进行处理!");
28 | }else{
29 | resultBean.setMessage("系统出现未知异常,请联系管理员电话:13756108xxx进行处理!");
30 | }
31 | return resultBean;
32 | }
33 |
34 | public static AjaxResponse success() {
35 | AjaxResponse resultBean = new AjaxResponse();
36 | resultBean.setIsok(true);
37 | resultBean.setCode(200);
38 | resultBean.setMessage("success");
39 | return resultBean;
40 | }
41 |
42 | public static AjaxResponse success(Object data) {
43 | AjaxResponse resultBean = new AjaxResponse();
44 | resultBean.setIsok(true);
45 | resultBean.setCode(200);
46 | resultBean.setMessage("success");
47 | resultBean.setData(data);
48 | return resultBean;
49 | }
50 |
51 |
52 | }
--------------------------------------------------------------------------------
/src/main/resources/application-dev.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8888
3 |
4 |
5 | spring:
6 | jackson:
7 | date-format: yyyy-MM-dd HH:mm:ss
8 | time-zone: GMT+8
9 | datasource:
10 | url: jdbc:mysql://192.168.161.3:3306/testdb?useUnicode=true&characterEncoding=utf-8&useSSL=false
11 | username: test
12 | password: 4rfv$RFV
13 | driver-class-name: com.mysql.jdbc.Driver
14 | freemarker:
15 | cache: false # 缓存配置 开发阶段应该配置为false 因为经常会改
16 | suffix: .html # 模版后缀名 默认为ftl
17 | charset: UTF-8 # 文件编码
18 | template-loader-path: classpath:/templates/
19 | redis:
20 | database: 0 # Redis 数据库索引(默认为 0)
21 | host: 192.168.161.3 # Redis 服务器地址
22 | port: 6379 # Redis 服务器连接端口
23 | password: 123456 # Redis 服务器连接密码(默认为空)
24 | lettuce:
25 | pool:
26 | max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 默认 8
27 | max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
28 | max-idle: 8 # 连接池中的最大空闲连接 默认 8
29 | min-idle: 0 # 连接池中的最小空闲连接 默认 0
30 | cache:
31 | type: redis
32 | redis:
33 | time-to-live: 600
34 |
35 | caching:
36 | ttlmap:
37 | article: 10
38 | articleAll: 20
39 |
40 | logging:
41 | config: classpath:log4j2-dev.xml
42 |
43 | mybatis:
44 | configuration:
45 | mapUnderscoreToCamelCase: true
46 |
47 |
48 | zimug:
49 | fastdfs:
50 | httpserver: http://192.168.161.3:8888/ #这个不是fastdfs属性,但是填上之后,在使用FastDFSClientUtil会得到完整的http文件访问路径
51 | connect_timeout: 5
52 | network_timeout: 30
53 | charset: UTF-8
54 | tracker_server: # tracker_server 可以配置成数组
55 | - 192.168.161.3:22122
56 | max_total: 50
57 | http_anti_steal_token: false # 如果有防盗链的话,这里true
58 | http_secret_key: # 有防盗链,这里填secret_key
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/controller/FastdfsController.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.controller;
2 |
3 | import com.zimug.bootlaunch.config.exception.AjaxResponse;
4 | import com.zimug.bootlaunch.config.exception.CustomException;
5 | import com.zimug.bootlaunch.config.exception.CustomExceptionType;
6 | import com.zimug.spring.fastdfs.FastDFSClientUtil;
7 | import org.springframework.stereotype.Controller;
8 | import org.springframework.web.bind.annotation.*;
9 | import org.springframework.web.multipart.MultipartFile;
10 |
11 | import javax.annotation.Resource;
12 |
13 | @Controller
14 | @RequestMapping("fastdfs")
15 | public class FastdfsController {
16 |
17 | @Resource
18 | private FastDFSClientUtil fastDFSClientUtil;
19 |
20 | @PostMapping("/upload")
21 | @ResponseBody
22 | public AjaxResponse upload(@RequestParam("file") MultipartFile file) {
23 |
24 | String fileId;
25 | try {
26 | String originalfileName = file.getOriginalFilename();
27 | fileId = fastDFSClientUtil.uploadFile(file.getBytes(),originalfileName.substring(originalfileName.lastIndexOf(".")));
28 | return AjaxResponse.success(fastDFSClientUtil.getSourceUrl(fileId));
29 | } catch (Exception e) {
30 | throw new CustomException(CustomExceptionType.SYSTEM_ERROR,"文件上传图片服务器失败");
31 | }
32 | }
33 |
34 |
35 | @DeleteMapping("/delete")
36 | @ResponseBody
37 | public AjaxResponse upload(@RequestParam String fileid) {
38 | try {
39 | fastDFSClientUtil.delete(fileid);
40 | byte[] imgfile = fastDFSClientUtil.downloadFile(fileid);
41 | } catch (Exception e) {
42 | throw new CustomException(CustomExceptionType.SYSTEM_ERROR,"文件删除失败");
43 | }
44 | return AjaxResponse.success();
45 | }
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/utils/AdrressIpUtils.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.utils;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 |
7 | public class AdrressIpUtils {
8 | /**
9 | * 获取Ip地址
10 | * @param request HttpServletRequest
11 | * @return ip
12 | */
13 | public static String getIpAdrress(HttpServletRequest request) {
14 | String Xip = request.getHeader("X-Real-IP");
15 | String XFor = request.getHeader("X-Forwarded-For");
16 | if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
17 | //多次反向代理后会有多个ip值,第一个ip才是真实ip
18 | int index = XFor.indexOf(",");
19 | if(index != -1){
20 | return XFor.substring(0,index);
21 | }else{
22 | return XFor;
23 | }
24 | }
25 | XFor = Xip;
26 | if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
27 | return XFor;
28 | }
29 | if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
30 | XFor = request.getHeader("Proxy-Client-IP");
31 | }
32 | if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
33 | XFor = request.getHeader("WL-Proxy-Client-IP");
34 | }
35 | if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
36 | XFor = request.getHeader("HTTP_CLIENT_IP");
37 | }
38 | if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
39 | XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
40 | }
41 | if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
42 | XFor = request.getRemoteAddr();
43 | }
44 | return XFor;
45 | }
46 | }
--------------------------------------------------------------------------------
/src/test/java/com/zimug/bootlaunch/restful/ArticleRestControllerTest.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.restful;
2 |
3 | import com.zimug.bootlaunch.controller.ArticleRestController;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.junit.Before;
6 | import org.junit.Test;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 | import org.springframework.http.HttpMethod;
9 | import org.springframework.test.web.servlet.MockMvc;
10 | import org.springframework.test.web.servlet.MvcResult;
11 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
12 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
13 | import org.springframework.test.web.servlet.setup.MockMvcBuilders;
14 |
15 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
16 |
17 | //@Transactional
18 | @Slf4j
19 | @SpringBootTest
20 | public class ArticleRestControllerTest {
21 |
22 | private MockMvc mockMvc;
23 |
24 | @Before
25 | public void setUp() {
26 | mockMvc = MockMvcBuilders.standaloneSetup(new ArticleRestController()).build();
27 | }
28 |
29 | /*@Test
30 | public void saveArticle() throws Exception {
31 |
32 | String article = "{\n" +
33 | " \"id\": 1,\n" +
34 | " \"author\": \"zimug\",\n" +
35 | " \"title\": \"手摸手教你开发spring boot\",\n" +
36 | " \"content\": \"c\",\n" +
37 | " \"createTime\": \"2017-07-16 05:23:34\",\n" +
38 | " \"reader\":[{\"name\":\"zimug\",\"age\":18},{\"name\":\"kobe\",\"age\":37}]\n" +
39 | "}";
40 | MvcResult result = mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/rest/article")
41 | .contentType("application/json").content(article))
42 | .andExpect(MockMvcResultMatchers.status().isOk())
43 | .andExpect(MockMvcResultMatchers.jsonPath("$.data.author").value("zimug"))
44 | .andExpect(MockMvcResultMatchers.jsonPath("$.data.reader[0].age").value(18))
45 | .andDo(print())
46 | .andReturn();
47 |
48 | log.info(result.getResponse().getContentAsString());
49 |
50 | }*/
51 | }
--------------------------------------------------------------------------------
/src/test/java/com/zimug/bootlaunch/restful/ArticleRestControllerTest2.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.restful;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 | import org.springframework.http.HttpMethod;
9 | import org.springframework.test.context.junit4.SpringRunner;
10 | import org.springframework.test.web.servlet.MockMvc;
11 | import org.springframework.test.web.servlet.MvcResult;
12 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
13 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
14 |
15 | import javax.annotation.Resource;
16 |
17 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
18 |
19 | //@Transactional
20 | @Slf4j
21 | @RunWith(SpringRunner.class)
22 | @AutoConfigureMockMvc
23 | @SpringBootTest
24 | public class ArticleRestControllerTest2 {
25 |
26 | @Resource
27 | private MockMvc mockMvc;
28 |
29 | /*@Before
30 | public void setUp() {
31 | mockMvc = MockMvcBuilders.standaloneSetup(new ArticleRestController()).build();
32 | }*/
33 |
34 | @Test
35 | public void saveArticle() throws Exception {
36 |
37 | String article = "{\n" +
38 | " \"id\": 1,\n" +
39 | " \"author\": \"zimug\",\n" +
40 | " \"title\": \"手摸手教你开发spring boot\",\n" +
41 | " \"content\": \"c\",\n" +
42 | " \"createTime\": \"2017-07-16 05:23:34\",\n" +
43 | " \"reader\":[{\"name\":\"zimug\",\"age\":18},{\"name\":\"kobe\",\"age\":37}]\n" +
44 | "}";
45 | MvcResult result = mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/rest/article")
46 | .contentType("application/json").content(article))
47 | .andExpect(MockMvcResultMatchers.status().isOk())
48 | .andExpect(MockMvcResultMatchers.jsonPath("$.data.author").value("zimug"))
49 | .andExpect(MockMvcResultMatchers.jsonPath("$.data.reader[0].age").value(18))
50 | .andDo(print())
51 | .andReturn();
52 |
53 | log.info(result.getResponse().getContentAsString());
54 |
55 | }
56 | }
--------------------------------------------------------------------------------
/src/main/resources/log4j2-dev.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/accesslog/AccessLogInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.accesslog;
2 |
3 | import com.zimug.bootlaunch.utils.AdrressIpUtils;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.web.servlet.HandlerInterceptor;
6 |
7 | import javax.servlet.http.HttpServletRequest;
8 | import javax.servlet.http.HttpServletResponse;
9 | import java.util.Date;
10 |
11 | @Slf4j
12 | public class AccessLogInterceptor implements HandlerInterceptor {
13 | //请求开始时间标识
14 | private static final String LOGGER_SEND_TIME = "SEND_TIME";
15 | //请求日志实体标识
16 | private static final String LOGGER_ACCESSLOG = "ACCESSLOG_ENTITY";
17 |
18 | /**
19 | * 进入SpringMVC的Controller之前开始记录日志实体
20 | */
21 | @Override
22 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
23 |
24 | //创建日志实体
25 | AccessLog accessLog = new AccessLog();
26 |
27 | // 设置IP地址
28 | accessLog.setIp(AdrressIpUtils.getIpAdrress(request));
29 |
30 | //设置请求方法,GET,POST...
31 | accessLog.setHttpMethod(request.getMethod());
32 |
33 | //设置请求路径
34 | accessLog.setUrl(request.getRequestURI());
35 |
36 | //设置请求开始时间
37 | request.setAttribute(LOGGER_SEND_TIME,System.currentTimeMillis());
38 |
39 | //设置请求实体到request内,方便afterCompletion方法调用
40 | request.setAttribute(LOGGER_ACCESSLOG,accessLog);
41 | return true;
42 | }
43 |
44 |
45 | @Override
46 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
47 |
48 | //获取本次请求日志实体
49 | AccessLog accessLog = (AccessLog) request.getAttribute(LOGGER_ACCESSLOG);
50 |
51 | //获取请求错误码,根据需求存入数据库,这里不保存
52 | int status = response.getStatus();
53 | accessLog.setHttpStatus(status);
54 |
55 | //request.getSession().getAttribute("username");
56 | //设置访问者(这里暂时写死)
57 | // 因为不同的应用可能将访问者信息放在session里面,有的通过request传递,
58 | // 总之可以获取到,但获取的方法不同
59 | accessLog.setUsername("admin");
60 |
61 | //当前时间
62 | long currentTime = System.currentTimeMillis();
63 |
64 | //请求开始时间
65 | long snedTime = Long.valueOf(request.getAttribute(LOGGER_SEND_TIME).toString());
66 |
67 |
68 | //设置请求时间差
69 | accessLog.setDuration(Integer.valueOf((currentTime - snedTime)+""));
70 |
71 | accessLog.setCreateTime(new Date());
72 | //将sysLog对象持久化保存
73 | log.info(accessLog.toString());
74 | }
75 | }
76 |
77 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/exception/WebExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config.exception;
2 |
3 | import org.springframework.validation.BindException;
4 | import org.springframework.validation.FieldError;
5 | import org.springframework.web.bind.MethodArgumentNotValidException;
6 | import org.springframework.web.bind.annotation.ControllerAdvice;
7 | import org.springframework.web.bind.annotation.ExceptionHandler;
8 | import org.springframework.web.bind.annotation.ResponseBody;
9 | import org.springframework.web.servlet.ModelAndView;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 |
13 | @ControllerAdvice
14 | public class WebExceptionHandler {
15 | @ExceptionHandler(ModelViewException.class)
16 | public ModelAndView viewExceptionHandler(HttpServletRequest req, ModelViewException e) {
17 | ModelAndView modelAndView = new ModelAndView();
18 |
19 | //将异常信息设置如modelAndView
20 | modelAndView.addObject("exception", e);
21 | modelAndView.addObject("url", req.getRequestURL());
22 | modelAndView.setViewName("error");
23 |
24 | //返回ModelAndView
25 | return modelAndView;
26 | }
27 |
28 | @ExceptionHandler(MethodArgumentNotValidException.class)
29 | @ResponseBody
30 | public AjaxResponse handleBindException(MethodArgumentNotValidException ex) {
31 | FieldError fieldError = ex.getBindingResult().getFieldError();
32 | return AjaxResponse.error(new CustomException(CustomExceptionType.USER_INPUT_ERROR,fieldError.getDefaultMessage()));
33 | }
34 |
35 |
36 | @ExceptionHandler(BindException.class)
37 | @ResponseBody
38 | public AjaxResponse handleBindException(BindException ex) {
39 | FieldError fieldError = ex.getBindingResult().getFieldError();
40 | return AjaxResponse.error(new CustomException(CustomExceptionType.USER_INPUT_ERROR,fieldError.getDefaultMessage()));
41 | }
42 |
43 | @ExceptionHandler(CustomException.class)
44 | @ResponseBody
45 | public AjaxResponse customerException(CustomException e) {
46 | if(e.getCode() == CustomExceptionType.SYSTEM_ERROR.getCode()){
47 | //400异常不需要持久化,将异常信息以友好的方式告知用户就可以
48 | //TODO 将500异常信息持久化处理,方便运维人员处理
49 | }
50 | return AjaxResponse.error(e);
51 | }
52 |
53 |
54 | @ExceptionHandler(Exception.class)
55 | @ResponseBody
56 | public AjaxResponse exception(Exception e) {
57 | //TODO 将异常信息持久化处理,方便运维人员处理
58 |
59 | //没有被程序员发现,并转换为CustomException的异常,都是其他异常或者未知异常.
60 | return AjaxResponse.error(new CustomException(CustomExceptionType.OTHER_ERROR,"未知异常"));
61 | }
62 |
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/service/ArticleMybatisRestServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.service;
2 |
3 | import com.zimug.bootlaunch.generator.testdb.Article;
4 | import com.zimug.bootlaunch.generator.testdb.ArticleMapper;
5 | import com.zimug.bootlaunch.model.ArticleVO;
6 | import com.zimug.bootlaunch.utils.DozerUtils;
7 | import lombok.extern.slf4j.Slf4j;
8 |
9 | import org.dozer.Mapper;
10 | import org.springframework.cache.annotation.CacheEvict;
11 | import org.springframework.cache.annotation.CachePut;
12 | import org.springframework.cache.annotation.Cacheable;
13 | import org.springframework.cache.annotation.Caching;
14 | import org.springframework.stereotype.Service;
15 |
16 | import javax.annotation.Resource;
17 | import java.util.List;
18 |
19 | @Slf4j
20 | @Service
21 | public class ArticleMybatisRestServiceImpl implements ArticleRestService{
22 |
23 | @Resource
24 | protected Mapper dozerMapper;
25 |
26 | @Resource
27 | private ArticleMapper articleMapper;
28 |
29 |
30 | @Override
31 | @Caching(
32 | evict = {
33 | @CacheEvict(value = "article",key = "#article.getId()"),
34 | @CacheEvict(value = "articleAll",allEntries = true)
35 | }
36 | )
37 | public ArticleVO saveArticle(ArticleVO article) {
38 | Article articlePO = dozerMapper.map(article,Article.class);
39 | articleMapper.insert(articlePO);
40 |
41 | //TODO 把readers村到数据库里面
42 | article.setId(articlePO.getId());
43 | return article;
44 | }
45 |
46 | @Override
47 | @Caching(
48 | evict = {
49 | @CacheEvict(value = "article",key = "#id"),
50 | @CacheEvict(value = "articleAll",allEntries = true)
51 | }
52 | )
53 | public void deleteArticle(Long id) {
54 | articleMapper.deleteByPrimaryKey(id);
55 | }
56 |
57 | @Override
58 | @Caching(
59 | evict = {
60 | @CacheEvict(value = "article",key = "#article.getId()"),
61 | @CacheEvict(value = "articleAll",allEntries = true)
62 | }
63 | )
64 | public ArticleVO updateArticle(ArticleVO article) {
65 | Article articlePO = dozerMapper.map(article,Article.class);
66 | articleMapper.updateByPrimaryKeySelective(articlePO);
67 | return article;
68 | }
69 |
70 | @Override
71 | @Cacheable(value="article",key = "#id",condition = "#id > 1")
72 | public ArticleVO getArticle(Long id) {
73 | //TODO 把读者信息查询出来赋值给ArticleVo
74 | return dozerMapper.map(articleMapper.selectByPrimaryKey(id),ArticleVO.class);
75 | }
76 |
77 | @Override
78 | @Cacheable(value="articleAll")
79 | public List getAll() {
80 | List articles = articleMapper.selectByExample(null);
81 | return DozerUtils.mapList(articles,ArticleVO.class);
82 |
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/test/java/com/zimug/bootlaunch/restful/ArticleRestControllerTest3.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.restful;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import com.zimug.bootlaunch.controller.ArticleRestController;
5 | import com.zimug.bootlaunch.model.ArticleVO;
6 | import com.zimug.bootlaunch.service.ArticleMybatisRestServiceImpl;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
11 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
12 | import org.springframework.boot.test.mock.mockito.MockBean;
13 | import org.springframework.http.HttpMethod;
14 | import org.springframework.test.context.junit4.SpringRunner;
15 | import org.springframework.test.web.servlet.MockMvc;
16 | import org.springframework.test.web.servlet.MvcResult;
17 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
18 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
19 |
20 | import javax.annotation.Resource;
21 |
22 | import static org.mockito.Mockito.when;
23 | import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
24 |
25 | //@Transactional
26 | @Slf4j
27 | @RunWith(SpringRunner.class)
28 | @AutoConfigureMockMvc
29 | @WebMvcTest(ArticleRestController.class)
30 | public class ArticleRestControllerTest3 {
31 |
32 | @Resource
33 | private MockMvc mockMvc;
34 |
35 | @MockBean
36 | ArticleMybatisRestServiceImpl articleRestService;
37 |
38 | /*@Before
39 | public void setUp() {
40 | mockMvc = MockMvcBuilders.standaloneSetup(new ArticleRestController()).build();
41 | }*/
42 |
43 | @Test
44 | public void saveArticle() throws Exception {
45 | String article = "{\n" +
46 | " \"id\": 1,\n" +
47 | " \"author\": \"zimug\",\n" +
48 | " \"title\": \"手摸手教你开发spring boot\",\n" +
49 | " \"content\": \"c\",\n" +
50 | " \"createTime\": \"2017-07-16 05:23:34\",\n" +
51 | " \"reader\":[{\"name\":\"zimug\",\"age\":18},{\"name\":\"kobe\",\"age\":37}]\n" +
52 | "}";
53 |
54 |
55 | ObjectMapper objectMapper = new ObjectMapper();
56 | ArticleVO articleObj = objectMapper.readValue(article,ArticleVO.class);
57 |
58 | //打桩
59 | when(articleRestService.saveArticle(articleObj)).thenReturn(articleObj);
60 |
61 |
62 | MvcResult result = mockMvc.perform(MockMvcRequestBuilders.request(HttpMethod.POST, "/rest/article")
63 | .contentType("application/json").content(article))
64 | .andExpect(MockMvcResultMatchers.status().isOk())
65 | .andExpect(MockMvcResultMatchers.jsonPath("$.data.author").value("zimug"))
66 | .andExpect(MockMvcResultMatchers.jsonPath("$.data.reader[0].age").value(18))
67 | .andDo(print())
68 | .andReturn();
69 |
70 | log.info(result.getResponse().getContentAsString());
71 |
72 | }
73 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/controller/ArticleRestController.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.controller;
2 |
3 | import com.zimug.bootlaunch.config.exception.AjaxResponse;
4 | import com.zimug.bootlaunch.model.ArticleVO;
5 | import com.zimug.bootlaunch.service.ArticleRestService;
6 | import io.swagger.annotations.ApiOperation;
7 | import io.swagger.annotations.ApiResponse;
8 | import io.swagger.annotations.ApiResponses;
9 | import lombok.extern.slf4j.Slf4j;
10 | import org.springframework.cache.annotation.Cacheable;
11 | import org.springframework.stereotype.Controller;
12 | import org.springframework.web.bind.annotation.*;
13 |
14 | import javax.annotation.Resource;
15 | import javax.validation.Valid;
16 |
17 |
18 | @Slf4j
19 | @Controller
20 | @RequestMapping("/rest")
21 | public class ArticleRestController {
22 |
23 | @Resource(name="articleMybatisRestServiceImpl")
24 | ArticleRestService articleRestService;
25 |
26 |
27 | @ApiOperation(value = "添加文章", notes = "添加新的文章", tags = "ArticleVO",httpMethod = "POST")
28 | @ApiResponses({
29 | @ApiResponse(code=200,message="成功",response=AjaxResponse.class),
30 | @ApiResponse(code=400,message="用户输入错误",response=AjaxResponse.class),
31 | @ApiResponse(code=500,message="系统内部错误",response=AjaxResponse.class)
32 | })
33 | //@RequestMapping(value = "/article", method = POST, produces = "application/json")
34 | @PostMapping("/article")
35 | public @ResponseBody AjaxResponse saveArticle(@RequestBody ArticleVO article) {
36 | /*public @ResponseBody AjaxResponse saveArticle(@RequestParam String id,
37 | @RequestParam String author) {*/
38 |
39 | log.info("saveArticle:{}",article);
40 |
41 | log.info("articleRestService return :" + articleRestService.saveArticle(article));
42 |
43 | return AjaxResponse.success(article);
44 | }
45 |
46 | //@RequestMapping(value = "/article/{id}", method = DELETE, produces = "application/json")
47 | @DeleteMapping("/article/{id}")
48 | public @ResponseBody AjaxResponse deleteArticle(@PathVariable Long id) {
49 |
50 | articleRestService.deleteArticle(id);
51 |
52 | return AjaxResponse.success(id);
53 | }
54 |
55 | //@RequestMapping(value = "/article/{id}", method = PUT, produces = "application/json")
56 | @PutMapping("/article/{id}")
57 | public @ResponseBody AjaxResponse updateArticle(@PathVariable Long id, @Valid @RequestBody ArticleVO article) {
58 | article.setId(id);
59 |
60 | articleRestService.updateArticle(article);
61 |
62 | return AjaxResponse.success();
63 | }
64 |
65 |
66 | //@RequestMapping(value = "/article/{id}", method = GET, produces = "application/json")
67 | @GetMapping( "/article/{id}")
68 | public @ResponseBody AjaxResponse getArticle(@PathVariable Long id) {
69 |
70 |
71 | return AjaxResponse.success(articleRestService.getArticle(id));
72 | }
73 |
74 |
75 | //@RequestMapping(value = "/article/{id}", method = GET, produces = "application/json")
76 | @GetMapping( "/article")
77 | public @ResponseBody AjaxResponse getAll() {
78 |
79 | return AjaxResponse.success(articleRestService.getAll());
80 | }
81 | }
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/generator/testdb/Article.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.generator.testdb;
2 |
3 | import java.io.Serializable;
4 | import java.util.Date;
5 |
6 | /**
7 | * article
8 | * @author
9 | */
10 | public class Article implements Serializable {
11 | private Long id;
12 |
13 | private String author;
14 |
15 | private String content;
16 |
17 | private Date createTime;
18 |
19 | private String title;
20 |
21 | private static final long serialVersionUID = 1L;
22 |
23 | public Long getId() {
24 | return id;
25 | }
26 |
27 | public void setId(Long id) {
28 | this.id = id;
29 | }
30 |
31 | public String getAuthor() {
32 | return author;
33 | }
34 |
35 | public void setAuthor(String author) {
36 | this.author = author;
37 | }
38 |
39 | public String getContent() {
40 | return content;
41 | }
42 |
43 | public void setContent(String content) {
44 | this.content = content;
45 | }
46 |
47 | public Date getCreateTime() {
48 | return createTime;
49 | }
50 |
51 | public void setCreateTime(Date createTime) {
52 | this.createTime = createTime;
53 | }
54 |
55 | public String getTitle() {
56 | return title;
57 | }
58 |
59 | public void setTitle(String title) {
60 | this.title = title;
61 | }
62 |
63 | @Override
64 | public boolean equals(Object that) {
65 | if (this == that) {
66 | return true;
67 | }
68 | if (that == null) {
69 | return false;
70 | }
71 | if (getClass() != that.getClass()) {
72 | return false;
73 | }
74 | Article other = (Article) that;
75 | return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
76 | && (this.getAuthor() == null ? other.getAuthor() == null : this.getAuthor().equals(other.getAuthor()))
77 | && (this.getContent() == null ? other.getContent() == null : this.getContent().equals(other.getContent()))
78 | && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
79 | && (this.getTitle() == null ? other.getTitle() == null : this.getTitle().equals(other.getTitle()));
80 | }
81 |
82 | @Override
83 | public int hashCode() {
84 | final int prime = 31;
85 | int result = 1;
86 | result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
87 | result = prime * result + ((getAuthor() == null) ? 0 : getAuthor().hashCode());
88 | result = prime * result + ((getContent() == null) ? 0 : getContent().hashCode());
89 | result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
90 | result = prime * result + ((getTitle() == null) ? 0 : getTitle().hashCode());
91 | return result;
92 | }
93 |
94 | @Override
95 | public String toString() {
96 | StringBuilder sb = new StringBuilder();
97 | sb.append(getClass().getSimpleName());
98 | sb.append(" [");
99 | sb.append("Hash = ").append(hashCode());
100 | sb.append(", id=").append(id);
101 | sb.append(", author=").append(author);
102 | sb.append(", content=").append(content);
103 | sb.append(", createTime=").append(createTime);
104 | sb.append(", title=").append(title);
105 | sb.append(", serialVersionUID=").append(serialVersionUID);
106 | sb.append("]");
107 | return sb.toString();
108 | }
109 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 一、代码配套书籍介绍
2 | * 本书发布于:[http://springboot.zimug.com](http://springboot.zimug.com),会持续创作更新。
3 | * 作者博客: [字母哥博客:www.zimug.com](http://www.zimug.com)
4 |
5 | ### **这本电子书的价值?**
6 | * 市面上售价70、80元一本的讲解spring boot的图书,因为出版章节及页数的限制,不可能讲解的全面细致,更多的是偏概念。而且技术是在不断发展的,很多内容都过时。
7 | * 本书会随着作者的知识更新,不断更新。**笔者自认为,这本电子书是目前市面上spring boot知识梳理最系统、全面、合理的一本电子书**。
8 |
9 | ## 二、内容概览
10 | * 第一章 spring boot 2.x基础及概念入门
11 | * 1.1.spring boot 产生的背景及其优势
12 | * 1.2.spring boot 2.x 新特性说明
13 | * 1.3.helloworld及项目结构介绍
14 | * 1.4.IDEA结合spring boot开发技巧
15 | * 第二章 RESTFul接口实现与测试
16 | * 2.1.RESTFul接口与http协议状态表述
17 | * 2.2.常用注解开发一个RESTFul接口
18 | * 2.3 JSON数据处理与PostMan测试
19 | * 2.4.使用Mockito编码完成接口测试
20 | * 2.5. 使用Swagger2构建API文档
21 | * 第三章 spring boot 配置原理实战
22 | * 3.1.结合配置加载讲解bean自动装配原理
23 | * 3.2.详解YAML语法及占位符语法
24 | * 3.3.获取自定义配置的两种实现方法
25 | * 3.4.配置文件注入值数据校验
26 | * 3.5.加载旧项目配置文件的两种方式
27 | * 3.6.profile不同环境使用不同配置
28 | * 3.7.配置及配置文件的加载优先级
29 | * 3.8.配置文件敏感字段加密
30 | * 第四章 常用web开发数据库框架
31 | * 4.1.整合Spring JDBC操作数据
32 | * 4.2 Spring JDBC多数据源的实现
33 | * 4.3.Spring JDBC JTA实现分布式事务
34 | * 4.4.ORM主流框架选型
35 | * 4.5.bean转换Dozer的快速上手
36 | * 4.6.整合Spring Data JPA操作数据
37 | * 4.7.Spring data JPA的多数据源实现
38 | * 4.8.JPA+atomikos实现分布式事务
39 | * 4.9.整合Mybatis操作数据
40 | * 4.10.Mybatis开发最佳实践总结
41 | * 4.11.Spring mybatis的多数据源实现
42 | * 4.12.mybatis+atomikos实现分布式事务
43 | * 4.13.Spring事务与分布式事务
44 | * 4.14.整合Spring data mongodb操作数据
45 | * 4.15.一行代码实现RESTFul接口
46 | * 第五章 静态资源与模板引擎的整合
47 | * 5.1.webjars与静态资源
48 | * 5.2.模板引擎选型与未来趋势
49 | * 5.3.web应用开发之整合jsp
50 | * 5.4.web应用开发之整合freemarker
51 | * 5.5.web应用开发之整合thymeleaf
52 | * 5.6.thymeleaf基础语法讲解
53 | * 5.7.thymeleaf内置对象与工具类
54 | * 5.8.公共片段(标签)与内联js
55 | * 第六章 生命周期内的拦截过滤与监听
56 | * 6.1.servlet与filter与listener的实现
57 | * 6.2.spring拦截器及请求链路说明
58 | * 6.3.自定义事件的发布与监听
59 | * 6.4.应用启动的监听
60 | * 第七章 嵌入式容器的配置与应用
61 | * 7.1.嵌入式的容器配置与调整
62 | * 7.2.切换到jetty&undertow容器
63 | * 7.3.打war包部署到外置tomcat容器
64 | * 第八章 统一全局异常处理
65 | * 8.1.设计一个优秀的异常处理机制
66 | * 8.2.自定义异常和相关数据结构
67 | * 8.3.全局异常处理ExceptionHandler
68 | * 8.4.服务端数据校验与全局异常处理
69 | * 8.5.AOP实现完美异常处理方案
70 | * 第九章 日志框架与全局日志管理
71 | * 9.1.日志框架的简介与选型
72 | * 9.2.logback日志框架整合使用
73 | * 9.3.log4j2日志框架整合与使用
74 | * 9.4.拦截器实现统一访问日志
75 | * 第十章 异步任务与定时任务
76 | * 10.1.实现Async异步任务
77 | * 10.2.为异步任务规划线程池
78 | * 10.3.通过@Scheduled实现定时任务
79 | * 10.4.quartz简单定时任务(内存持久化)
80 | * 10.5.quartz动态定时任务(数据库持久化)
81 | * 第十一章 redis缓存与session共享
82 | * 11.1.使用docker安装redis
83 | * 11.2.redis数据结构与应用场景
84 | * 11.3.使用redisTemplate操作数据
85 | * 11.4.使用Redis Repository操作数据
86 | * 11.5.spring cache基本用法
87 | * 11.6.详述缓存声明式注解的使用
88 | * 11.7.个性化自定义缓存到期时间
89 | * 11.8.集群多节点应用session共享
90 | * 第十二章 整合分布式文件系统fastdfs
91 | * 12.1.fastdfs简介及架构说明
92 | * 12.2.使用docker安装fastdfs
93 | * 12.3.开发一个自定义fastdfs-starter
94 | * 12.4.整合fastdfs操作文件数据
95 | * 第十三章 服务器推送技术
96 | * 13.1.主流服务器推送技术说明
97 | * 13.2.服务端推送事件SSE
98 | * 13.3.双向实时通信websocket
99 | * 第十四章 消息队列的整合与使用
100 | * 14.1.消息队列与JMS规范简介
101 | * 14.2.使用docker安装activeMQ
102 | * 14.3.activeMQ实现点对点队列
103 | * 14.4.activeMQ实现发布订阅队列
104 | * 14.5.docker安装RocketMQ
105 | * 14.6.RocketMQ实现2种消费模式
106 | * 14.7.RocketMQ实现分布式事务
107 | * 第十五章 邮件发送的整合与使用
108 | * 15.1.基础协议及邮件配置整合
109 | * 15.2.发送html和基于模板的邮件
110 | * 15.3.发送带附件和内联附件邮件
111 | * 第十六章 响应式框架webflux
112 | * 16.1.webflux快速入门
113 | * 16.2.注解方式实现restful接口
114 | * 16.3.webflux整合mongodb
115 | * 16.4.webclient单元测试的编写
116 | * 番外篇:周边技术生态
117 | * 如何使用git查看本教程代码
118 | * centos7安装docker图文详解
119 | * docker安装mongodb(单点)图文详解
120 | * 如何使用mybatis自动生成的代码
121 |
122 |
123 |
--------------------------------------------------------------------------------
/src/main/java/com/zimug/bootlaunch/config/RedisConfig.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.config;
2 |
3 | import com.fasterxml.jackson.annotation.JsonAutoDetect;
4 | import com.fasterxml.jackson.annotation.PropertyAccessor;
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 | import lombok.Data;
7 | import org.springframework.boot.context.properties.ConfigurationProperties;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 | import org.springframework.data.redis.cache.RedisCacheConfiguration;
11 | import org.springframework.data.redis.cache.RedisCacheManager;
12 | import org.springframework.data.redis.cache.RedisCacheWriter;
13 | import org.springframework.data.redis.connection.RedisConnectionFactory;
14 | import org.springframework.data.redis.core.RedisTemplate;
15 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
16 | import org.springframework.data.redis.serializer.RedisSerializationContext;
17 | import org.springframework.data.redis.serializer.StringRedisSerializer;
18 | import org.springframework.stereotype.Component;
19 |
20 | import java.time.Duration;
21 | import java.util.HashMap;
22 | import java.util.Map;
23 |
24 | @Data
25 | @Configuration
26 | @Component
27 | @ConfigurationProperties(prefix = "caching")
28 | public class RedisConfig {
29 |
30 | @Bean
31 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
32 | RedisTemplate redisTemplate = new RedisTemplate();
33 | redisTemplate.setConnectionFactory(redisConnectionFactory);
34 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
35 |
36 | ObjectMapper objectMapper = new ObjectMapper();
37 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
38 | objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
39 |
40 | jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
41 |
42 | //重点在这四行代码
43 | redisTemplate.setKeySerializer(new StringRedisSerializer());
44 | redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
45 | redisTemplate.setHashKeySerializer(new StringRedisSerializer());
46 | redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
47 |
48 | redisTemplate.afterPropertiesSet();
49 | return redisTemplate;
50 | }
51 |
52 |
53 | //自定义redisCacheManager
54 | @Bean
55 | public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
56 | RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
57 |
58 | RedisCacheManager redisCacheManager = new RedisCacheManager(redisCacheWriter,
59 | this.buildRedisCacheConfigurationWithTTL(redisTemplate,RedisCacheConfiguration.defaultCacheConfig().getTtl().getSeconds()), //默认的redis缓存配置
60 | this.getRedisCacheConfigurationMap(redisTemplate)); //针对每一个cache做个性化缓存配置
61 |
62 | return redisCacheManager;
63 | }
64 |
65 | //配置注入,key是缓存名称,value是缓存有效期
66 | private Map ttlmap;
67 |
68 | //根据ttlmap的属性装配结果,个性化RedisCacheConfiguration
69 | private Map getRedisCacheConfigurationMap(RedisTemplate redisTemplate) {
70 | Map redisCacheConfigurationMap = new HashMap<>();
71 |
72 | for(Map.Entry entry : ttlmap.entrySet()){
73 | String cacheName = entry.getKey();
74 | Long ttl = entry.getValue();
75 | redisCacheConfigurationMap.put(cacheName,this.buildRedisCacheConfigurationWithTTL(redisTemplate,ttl));
76 | }
77 |
78 | return redisCacheConfigurationMap;
79 | }
80 |
81 |
82 | //让缓存的序列化方式使用redisTemplate.getValueSerializer(),并未每一个缓存分别设置ttl
83 | private RedisCacheConfiguration buildRedisCacheConfigurationWithTTL(RedisTemplate redisTemplate,Long ttl){
84 | return RedisCacheConfiguration.defaultCacheConfig()
85 | .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()))
86 | .entryTtl(Duration.ofSeconds(ttl));
87 | }
88 | }
--------------------------------------------------------------------------------
/src/test/java/com/zimug/bootlaunch/redis/RedisConfigTest.java:
--------------------------------------------------------------------------------
1 | package com.zimug.bootlaunch.redis;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import com.zimug.bootlaunch.model.Address;
5 | import com.zimug.bootlaunch.model.Person;
6 | import org.junit.Assert;
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.boot.test.context.SpringBootTest;
11 | import org.springframework.data.redis.core.*;
12 | import org.springframework.data.redis.hash.HashMapper;
13 | import org.springframework.data.redis.hash.Jackson2HashMapper;
14 | import org.springframework.test.context.junit4.SpringRunner;
15 |
16 | import javax.annotation.Resource;
17 | import java.util.Map;
18 | import java.util.Set;
19 | import java.util.concurrent.TimeUnit;
20 |
21 | @RunWith(SpringRunner.class)
22 | @SpringBootTest
23 | public class RedisConfigTest {
24 |
25 | @Autowired
26 | private StringRedisTemplate stringRedisTemplate;
27 |
28 | /*@Autowired
29 | private RedisTemplate redisTemplate;*/
30 |
31 | @Resource(name = "redisTemplate")
32 | private ValueOperations valueOperations;
33 |
34 | @Resource(name = "redisTemplate")
35 | private HashOperations hashOperations;
36 |
37 | @Resource(name = "redisTemplate")
38 | private ListOperations listOperations;
39 |
40 | @Resource(name = "redisTemplate")
41 | private SetOperations setOperations;
42 |
43 | @Resource(name = "redisTemplate")
44 | private ZSetOperations zSetOperations;
45 |
46 | @Test
47 | public void testValueObj() throws Exception{
48 | Person person = new Person("kobe","byrant");
49 | person.setAddress(new Address("南京","中国"));
50 | //ValueOperations operations = redisTemplate.opsForValue();
51 | valueOperations.set("player:2",person,20,TimeUnit.SECONDS); //20秒之后数据消失
52 |
53 | Person getBack = (Person)valueOperations.get("player:1");
54 | System.out.println(getBack);
55 | }
56 |
57 | @Test
58 | public void testSetOperation() throws Exception{
59 | Person person = new Person("boke","byrant");
60 | Person person2 = new Person("curry","stephen");
61 | setOperations.add("playerset",person,person2);
62 | Set