Tomcat配置
配置Tomcat
- 配置Servlet容器
server.port=#配置程序端口,默认为8080
server.session-timeout=#用户会话session过期时间,以秒为单位
server.context-path=#配置访问路径,默认为/
- 配置Tomcat
server.tomcat.uri-encoding=#配置Tomcat编码,默认为UTF-8
server.tomcat.compression=#Tomcat是否开启压缩,默认为关闭
代码配置Tomcat
- 如果你需要通过代码的方式配置Servlet容器,则可以注册一个实现EmbeddedServletContainerCustomizer接口的Bean;若想直接配置Tomcat,Jetty则可以直接定义TomcatEmbeddedServletContainerCustomizer,JettyEmbeddedServletContainerCustomizer
新建类的配置
@component
public class CustomServletContainer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfiguraEmbeddedServletContainer container) {
container.setPort("9999");
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"));
container.setSessionTimeout(10, TimeUnit.MINUTES);
}
}
当前配置文件配置
@SpringBootApplication
public class Ch7Application {
public static void main(String[] args) {
SpringApplication.run(Ch7Application.class, args);
}
@Componect
public static class CustomServletContainer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort("9999");
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"));
container.setSessionTimeout(10, TimeUnit.MINUTES);
}
}
}
特定配置
@Bean
public EmbeddedServletContainerCustomizerFactory servletContainer() {
TomcatEmbeddedServletContainerCustomizerFactory factory =
new TomcatEmbeddedServletContainerCustomizerFactory();
factory.setPort("9999");
factory.addErrorType(new ErrorType(HttpStatus.NOT_FOUND, "/404.html"));
factory.setSessionTimeout(10, TimeUnit.MINUTES);
return factory;
}
Favicon配置
关闭Favicon
# 我们可以在application.properties中设置关闭Favicon,默认为开启
spring.mvc.favicon.enabled=false
设置自己的Favicon
- 若需要设置自己的Favicon,则只需要将自己的favicon.ico文件放置在类路径根目录、类路径resources/下、类路径static/下或者类路径public/下,注意:文件名不能变
Spring-Boot的数据访问
SpringBoot整合JdbcTemplate
环境准备
- 引入spring-boot-starter-jdbc的依赖
- 引入mysql连接类和连接池依赖
- 在application.properties文件配置mysql的驱动类,数据库地址,数据库账号、密码信息
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=1111
SpringBoot整合JPA
- JPA全称Java Persistence API。JPA通过注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
- JPA的目标之一是制定一个可以由很多供应商实现的API,并且开发人与可以编码来实现该API,而不是使用私有供应商特有的API
- JPA是需要Provider来实现其功能的,Hibernate就是JPA Provider中很强的一个。从功能上来说,JPA就是Hibernate功能的一个子集
环境准备
- 引入spring-boot-starter-data-jpa依赖:
- 引入mysql连接类和连接池依赖
- 在application.properties文件配置mysql的驱动类,数据库地址,数据库账号、密码信息
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
username: root
password: 1111
jpa:
hibernate:
ddl-auto: update
show-sql: true
## 注意,如果通过jpa在数据库中建表,将jpa.hibernate,ddl-auto改为create,建完表之后,要改为update,要不然每次重启工程会删除表并新建。
创建实体类
+通过@Entity 表明是一个映射的实体类, @Id表明id, @GeneratedValue 字段自动生成
@Entity
public class Account {
@Id
@GeneratedValue
private int id ;
private String name ;
private double money;
// getter setter
}
Dao层
- 数据访问层,通过编写一个继承自JpaRepository的接口就能万恒数据访问,其中包含了基本的单表查询的方法,非常的方便。值得注意的是,这个Account是对象名,不是具体的表名,另外Integer是主键的类型,一般为Integer或者Long
public interface AccountDao extends JpaRepository<Account,Integer> {
}
SpringBoot整合beetlSql
- beetlSql是一个全功能的DAO工具,同时具有Hibernate的优点和MyBatis优点,适用于以SQL为中心,同时又需求工具能自动生成大量常用的SQL的应用
beetlSql优点
- 开发效率
- 无需注解,自动使用大量内置SQL,轻易完成CRUD功能,节省50%的开发工作量
- 数据模型支持POJO,也支持Map/List这种快速模型,也支持混合模型
- SQL模板基于Beetl实现,更容易写和调试,以及扩展
- 维护性
- SQL更加简洁,Markdown方式集中管理,同时方便程序开发和数据库SQL调试
- 可以自动将SQL文件映射为dao接口类
- 灵活直观的支持一对一,一对多,多对多关系映射而不引入复杂的OR Mapping概念和技术
- 具备Interceptor功能,可以调试,性能诊断SQL,以及扩展其他功能
- 其他
- 内置支持主从数据库支持的开源工具
- 支持跨数据库平台,开发者所需工作减少到最小
- 目前跨数据库支持MySQL,postgres,oracle,sqlServer,h2,sqllite,DB2
环境准备
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetlsql</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
整合阶段
- 由于SpringBoot没有对beetlSql的快速启动装配,所以需要我自己导入相关的Bean,包括数据源,包扫描,事务管理等
- 在application中加入以下代码:
@Bean(initMethod = "init", name = "beetlConfig")
public BeetlGroupUtilConfiguration getBeetlGroupUtilConfiguration() {
BeetlGroupUtilConfiguration beetlGroupUtilConfiguration = new BeetlGroupUtilConfiguration();
ResourcePatternResolver patternResolver = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader());
try {
// WebAppResourceLoader 配置root路径是关键
WebAppResourceLoader webAppResourceLoader = new WebAppResourceLoader(patternResolver.getResource("classpath:/templates").getFile().getPath());
beetlGroupUtilConfiguration.setResourceLoader(webAppResourceLoader);
} catch (IOException e) {
e.printStackTrace();
}
//读取配置文件信息
return beetlGroupUtilConfiguration;
}
@Bean(name = "beetlViewResolver")
public BeetlSpringViewResolver getBeetlSpringViewResolver(@Qualifier("beetlConfig") BeetlGroupUtilConfiguration beetlGroupUtilConfiguration) {
BeetlSpringViewResolver beetlSpringViewResolver = new BeetlSpringViewResolver();
beetlSpringViewResolver.setContentType("text/html;charset=UTF-8");
beetlSpringViewResolver.setOrder(0);
beetlSpringViewResolver.setConfig(beetlGroupUtilConfiguration);
return beetlSpringViewResolver;
}
//配置包扫描
@Bean(name = "beetlSqlScannerConfigurer")
public BeetlSqlScannerConfigurer getBeetlSqlScannerConfigurer() {
BeetlSqlScannerConfigurer conf = new BeetlSqlScannerConfigurer();
conf.setBasePackage("com.forezp.dao");
conf.setDaoSuffix("Dao");
conf.setSqlManagerFactoryBeanName("sqlManagerFactoryBean");
return conf;
}
@Bean(name = "sqlManagerFactoryBean")
@Primary
public SqlManagerFactoryBean getSqlManagerFactoryBean(@Qualifier("datasource") DataSource datasource) {
SqlManagerFactoryBean factory = new SqlManagerFactoryBean();
BeetlSqlDataSource source = new BeetlSqlDataSource();
source.setMasterSource(datasource);
factory.setCs(source);
factory.setDbStyle(new MySqlStyle());
factory.setInterceptors(new Interceptor[]{new DebugInterceptor()});
factory.setNc(new UnderlinedNameConversion());//开启驼峰
factory.setSqlLoader(new ClasspathLoader("/sql"));//sql文件路径
return factory;
}
//配置数据库
@Bean(name = "datasource")
public DataSource getDataSource() {
return DataSourceBuilder.create().url("jdbc:mysql://127.0.0.1:3306/test").username("root").password("123456").build();
}
//开启事务
@Bean(name = "txManager")
public DataSourceTransactionManager getDataSourceTransactionManager(@Qualifier("datasource") DataSource datasource) {
DataSourceTransactionManager dsm = new DataSourceTransactionManager();
dsm.setDataSource(datasource);
return dsm;
}
- 在resource包下,加META_INF文件夹,文件夹中加入spring-devtools.properties
restart.include.beetl=/beetl-2.3.2.jar
restart.include.beetlsql=/beetlsql-2.3.1.jar
Dao层
public interface AccountDao extends BaseMapper<Account> {
@SqlStatement(params = "name")
Account selectAccountByName(String name);
}
- 接口继承BaseMapper,就能够获取表单查询的一些性质,当你需要自定义sql的时候,只需要在resource/sql/account.md文件下书写文件
selectAccountByName
===
* 根据name获取account
select * from account where name = #name#
- === 上面是唯一标识,对应于接口的方法名
-
- 后面是注释
SpringBoot整合MyBatis
环境准备
- 引入mybatis-spring-boot-starter的依赖
- 引入数据库连接依赖
- 在application.properties配置文件中配置数据源
Dao层
@Mapper
public interface AccountMapper {
@Insert("insert into account(name, money) values(#{name}, #{money})")
int add(@Param("name") String name, @Param("money") double money);
@Update("update account set name = #{name}, money = #{money} where id = #{id}")
int update(@Param("name") String name, @Param("money") double money, @Param("id") int id);
@Delete("delete from account where id = #{id}")
int delete(int id);
@Select("select id, name as name, money as money from account where id = #{id}")
Account findAccount(@Param("id") int id);
@Select("select id, name as name, money as money from account")
List<Account> findAccountList();
}
Service层
@Service
public class AccountService {
@Autowired
private AccountMapper accountMapper;
public int add(String name, double money) {
return accountMapper.add(name, money);
}
public int update(String name, double money, int id) {
return accountMapper.update(name, money, id);
}
public int delete(int id) {
return accountMapper.delete(id);
}
public Account findAccount(int id) {
return accountMapper.findAccount(id);
}
public List<Account> findAccountList() {
return accountMapper.findAccountList();
}
}
SpringBoot开启声明式事务
- SpringBoot开启事务很简单,只需要一个注解@Transactional就可以了。因为在SpringBoot中已经默认对JPA,jdbc,MyBatis开启了事务。引入它们依赖的时候,事务就默认开启了
环境准备
- 在application.properties配置文件中添加:
mybatis.mapper-location=classpath*:mybatis/*Mapper.xml
mybatis.type-aliase-package=com.kings.entity
Dao层
public interface AccountMapper{
int update(@Param("money") double money, @Param("id") int id);
}
Mapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.forezp.dao.AccountMapper2">
<update id="update">
UPDATE account set money=#{money} WHERE id=#{id}
</update>
</mapper>
Service层
@Service
public class AccountService {
@Autowired
AccountMapper accountMapper;
@Transactional
public void transfer() throws RuntimeException{
accountMapper.update(90,1);//用户1减10块 用户2加10块
int i=1/0;
accountMapper.update(110,2);
}
}
SpringBoot整合MongoDB
环境准备
- 引入spring-boot-starter-data-mongodb的依赖
- 如果mongodb端口是默认端口,并且没有设置密码,可不配置,SpringBoot会开启默认的
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/springboot-db
- mongodb设置了密码,可以这样设置
spring.data.mongodb.uri=mongodb://name:pass@127.0.0.1:27017/dbname
实体类
public class Customer {
@Id
public String id;
public String firstName;
public String lastName;
public Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"Customer[id=%s, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
}
Dao层
- 写一个接口,继承MongoRepository,这个接口有了基本的CURD的功能。如果你想自定义一些查询,比如根据firstName来查询,或者根据lastName来查询,值需要定义一个方法即可。注意firstName严格按照存入的mongodb的字段对应。在典型的Java的应用程序,写这样一个接口的方法,需要自己实现,但是在SpringBoot中,你只需要按照格式写一个接口名和对应的参数就可以了
public interface CustomerRepository extends MongoRepository<Customer, String> {
public Customer findByFirstName(String firstName);
public List<Customer> findByLastName(String lastName);
}
测试
@SpringBootApplication
public class SpringbootMongodbApplication implements CommandLineRunner {
@Autowired
private CustomerRepository repository;
public static void main(String[] args) {
SpringApplication.run(SpringbootMongodbApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
repository.deleteAll();
// save a couple of customers
repository.save(new Customer("Alice", "Smith"));
repository.save(new Customer("Bob", "Smith"));
// fetch all customers
System.out.println("Customers found with findAll():");
System.out.println("-------------------------------");
for (Customer customer : repository.findAll()) {
System.out.println(customer);
}
System.out.println();
// fetch an individual customer
System.out.println("Customer found with findByFirstName('Alice'):");
System.out.println("--------------------------------");
System.out.println(repository.findByFirstName("Alice"));
System.out.println("Customers found with findByLastName('Smith'):");
System.out.println("--------------------------------");
for (Customer customer : repository.findByLastName("Smith")) {
System.out.println(customer);
}
}
SpringBoot整合Redis
环境准备
- 引入spring-boot-starter-data-redis的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置数据源
spring:
redis:
host: localhost
port: 6379
#password:
database: 1
pool:
max-active: 8
max-wait: -1
max-idle: 500
min-idle: 0
timeout: 0
Dao层
- 通过redisTemplate来访问redis
@Repository
public class RedisDao {
@Autowired
private StringRedisTemplate template;
public void setKey(String key,String value){
ValueOperations<String, String> ops = template.opsForValue();
ops.set(key,value,1, TimeUnit.MINUTES);//1分钟过期
}
public String getValue(String key){
ValueOperations<String, String> ops = this.template.opsForValue();
return ops.get(key);
}
}
单元测试
@Repository
public class RedisDao {
@Autowired
private StringRedisTemplate template;
public void setKey(String key,String value){
ValueOperations<String, String> ops = template.opsForValue();
ops.set(key,value,1, TimeUnit.MINUTES);//1分钟过期
}
public String getValue(String key){
ValueOperations<String, String> ops = this.template.opsForValue();
return ops.get(key);
}
}
Spring-Boot的架构文档
SpringBoot集成Restdocs
环境准备
- 引入spring-restdocs-mockmvc依赖
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
- 在SpringBoot创建一个Controller
@RestController
public class HomeController {
@GetMapping("/")
public Map<String, Object> getting(){
return Colections.singletomMap("message", "Hello World");
}
}
通过单元测试生成API文档
- restdocs是通过单元测试生成snippets文件,然后snippets根据插件生成htm文档的
- 创建一个单元测试类:
@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
@AutoConfigureRestCocs(outputDir = "target/snippets")
public class WebLayerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void shouldReturnDefaultMessage() throws Exception {
this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(conteinsString("Hello World")))
.andDo(document("home"));
}
}
- 其中,@AutoConfigureRestDocs注解开启了生成snippets文件,并指定了存放位置
- 启动单元测试,测试通过。会发现target文件夹下生成了一个snippets文件夹
└── target
└── snippets
└── home
└── httpie-request.adoc
└── curl-request.adoc
└── http-request.adoc
└── http-response.adoc
- 默认情况下,snippets是Asciidoctor格式的文件,包括request和response,另外两种httpie和curl两种流行的命令行的http请求模式
- 到目前为止,只生成了snippets文件,需要用snippets文件生成文档
使用snippets文件生成文档
- 创建一个新文件 src/main/asciidoc/index.adoc:
= 用 Spring REST Docs 构建文件
This is an example output for a service running at http://127.0.0.1:8080:
.request
include::{snippets}/home/http-request.adoc[]
.response
include::{snippets}/home/http-response.adoc[]
这个例子很简单,通过单元测试和一些简单的配置就能够得到api文档了
-
adoc的书写形式,参考:http://docs.spring.io/spring-restdocs/docs/current/reference/html5/
-
引入asciidoctot-maven-plugin插件
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-docs</id>
<phase>prepare-package</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<sourceDocumentName>index.adoc</sourceDocumentName>
<backend>html</backend>
<attributes>
<snippets>${project.build.directory}/snippets</snippets>
</attributes>
</configuration>
</execution>
</executions>
</plugin>
- 这时只需要通过mvnw package命令就可以生成文档了
SpringBoot集成swagger2
- swagger是一个功能强大的api框架,它的集成非常简单,不仅提供了在线文档的查阅,而且还提供了在线文档的测试。另外swagger很容易构建restful风格的api,简单优雅
环境准备
- 引入swagger依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
- 编写配置类
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.forezp.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("springboot利用swagger构建api文档")
.description("简单优雅的restfun风格,http://blog.csdn.net/forezp")
.termsOfServiceUrl("http://blog.csdn.net/forezp")
.version("1.0")
.build();
}
}
- 通过@Configuration注解,表明它是一个配置类。
- 通过@EnableSwagger2开启swagger2
- apilNfo()方法配置一些基本信息
- apis()方法指定扫描的包会生成文档
生产文档的注解
- swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息等等
- @Api:修饰整个类。描述Controller的作用
- @ApiOperation:描述一个类的一个方法,或者一个接口
- @ApiParam:单个参数描述
- @ApiProperty:用对象接受参数时,描述对象的一个字段
- @ApiResponse:HTTP响应其中1个描述
- @ApiResponses:HTTP响应整体描述
- @ApiIgnore:使用该注解忽略这个API
- @ApiError:发生错误返回的信息
- @ApiParamImplicitl:一个请求参数
- @ApiParamsImplicit:多个请求参数
测试说明
/**
* 用户创建某本图书 POST /books/
* 用户修改对某本图书 PUT /books/:id/
* 用户删除对某本图书 DELETE /books/:id/
* 用户获取所有的图书 GET /books
* 用户获取某一图书 GET /Books/:id
* Created by fangzhipeng on 2017/4/17.
* 官方文档:http://swagger.io/docs/specification/api-host-and-base-path/
*/
@RestController
@RequestMapping(value = "/books")
public class BookContrller {
Map<Long, Book> books = Collections.synchronizedMap(new HashMap<Long, Book>());
@ApiOperation(value="获取图书列表", notes="获取图书列表")
@RequestMapping(value={""}, method= RequestMethod.GET)
public List<Book> getBook() {
List<Book> book = new ArrayList<>(books.values());
return book;
}
@ApiOperation(value="创建图书", notes="创建图书")
@ApiImplicitParam(name = "book", value = "图书详细实体", required = true, dataType = "Book")
@RequestMapping(value="", method=RequestMethod.POST)
public String postBook(@RequestBody Book book) {
books.put(book.getId(), book);
return "success";
}
@ApiOperation(value="获图书细信息", notes="根据url的id来获取详细信息")
@ApiImplicitParam(name = "id", value = "ID", required = true, dataType = "Long",paramType = "path")
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public Book getBook(@PathVariable Long id) {
return books.get(id);
}
@ApiOperation(value="更新信息", notes="根据url的id来指定更新图书信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "图书ID", required = true, dataType = "Long",paramType = "path"),
@ApiImplicitParam(name = "book", value = "图书实体book", required = true, dataType = "Book")
})
@RequestMapping(value="/{id}", method= RequestMethod.PUT)
public String putUser(@PathVariable Long id, @RequestBody Book book) {
Book book1 = books.get(id);
book1.setName(book.getName());
book1.setPrice(book.getPrice());
books.put(id, book1);
return "success";
}
@ApiOperation(value="删除图书", notes="根据url的id来指定删除图书")
@ApiImplicitParam(name = "id", value = "图书ID", required = true, dataType = "Long",paramType = "path")
@RequestMapping(value="/{id}", method=RequestMethod.DELETE)
public String deleteUser(@PathVariable Long id) {
books.remove(id);
return "success";
}
@ApiIgnore//使用该注解忽略这个API
@RequestMapping(value = "/hi", method = RequestMethod.GET)
public String jsonTest() {
return " hi you!";
}
}
- 通过相关注解,就可以让swagger2生成相应的文档。如果你不需要某接口生成文档,只需要在加@ApiIgnore注解即可。需要说明的是:如果请求参数在url上,@ApiImplicitParam上加 paramType=“path”
- 启动工程,访问:http://localhost:8080/swagger-ui.html