天天看点

Spring boot 框架介绍1、泛型Service2、Spring boot 入门3 SpringBoot深入介绍4 IDEA Spring boot 热部署

1、泛型Service

以前Service写法

public abstract class BaseService<M extends Serializable> {  
    private BaseRepository<M> repository;  
    public void setRepository(BaseRepository<M> repository) {  
        this.repository = repository;  
    }  
    public void save(M m) {  
        repository.save(m);  
    }  
}  
@Service  
public class UserService extends BaseService<User> {  
    @Autowired  
    public void setUserRepository(UserRepository userRepository) {  
        setRepository(userRepository);  
    }  
}  

@Service  
public class OrganizationService extends BaseService<Organization> {  
    @Autowired  
    public void setOrganizationRepository(OrganizationRepository organizationRepository) {  
        setRepository(organizationRepository);  
    }  
}  
           

可以看到,以前必须再写一个setter方法,然后指定注入的具体类型,然后进行注入;

泛型Service的写法

public abstract class BaseService<M extends Serializable> {  
    @Autowired  
    protected BaseRepository<M> repository;  

    public void save(M m) {  
        repository.save(m);  
    }  
}  

@Service  
public class UserService extends BaseService<User> {  
}  

@Service  
public class OrganizationService extends BaseService<Organization> {  
}  
           

2、Spring boot 入门

1) 继承spring-boot-starter-parent

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
           

2) 引入spring-boot-starter-web包

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
           

3) 编写启动Class

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
           

4) 项目启动

有两张方式启动

在项目目录下执行mvn spring-boot:run

在DemoApplication 类中执行右键Run DemoApplication

至此SpringBoot项目已经完成

3 SpringBoot深入介绍

1) 页面渲染

静态文件放到src\main\resources目录访问时可以通过http://ip:port/cxt/static/js/***.js
页面展现文件放到src\main\resources\templates目录下
spring-boot 不推荐JSP
可以通过freemarker、velocity、thymeleaf 等模板引擎

freemarker:渲染文件以ftl结尾
           
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
           
velocity:渲染文件以vm结尾(SpringBoot 1.5.x之后已经不再支持Velocity)
           
<dependency>    
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-velocity</artifactId>  
</dependency>  
           
thymeleaf:渲染文件以html结尾
           
<dependency>  
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>  
</dependency>
           

可同时支持freemarker和thymeleaf

2) 应用部署

添加插件
           
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
           

执行mvn clean package 可以得到demo-0.0.1-SNAPSHOT.jar

通过命令java -jar target/demo-0.0.1-SNAPSHOT.jar运行程序

3) 配置文件介绍

配置文件支持properties或yml文件,写法区别如下:

spring.redis.cluster.nodes[]=:  
spring.redis.cluster.nodes[]=:  
或  
spring:  
   redis:  
      cluster:  
         nodes:  
            - :  
            - :  
           
常用配置如下:
           
server.port=            #项目启动端口号,默认为8080
server.context-path=/demo   #项目启动应用名称,默认为空
           

控制日志级别

通过 logging.level.*= LEVEL(LEVEL是TRACE,DEBUG,INFO,WARN,FATAL,OFF)中的一个

这样表示项目中所有的日志级别都是一样的.也可以精准控制到具体的一块

logging.level.org.springframework.web: DEBUG //org.springframework.web包下面的日志级别是DEBUG的  
logging.level.org.hibernate: ERROR //org.hibernate包下面的日志级别是ERROR  
logging.level.com.ibigsea.*: INFO //com.ibigsea包下面的日志级别是INFO  
           

Profile配置

Profile是Spring用来针对不同环境对不同配置提供支持的,全局Profile配置使用

application-{profile}.properties 如:application-prod.properties

在本地模拟出一个开发环境和生产环境

创建application-prd.properties 和 application-dev.properties

项目结构

Spring boot 框架介绍1、泛型Service2、Spring boot 入门3 SpringBoot深入介绍4 IDEA Spring boot 热部署

application-dev.properties

application-prd.properties

application.properties(设置启动环境)

spring.profiles.active=prd 
           

除了上面这种配置方式,我们还有一种更简便的方式来配置多种环境,通过命令行参数配置

删除多余的properties文件

Spring boot 框架介绍1、泛型Service2、Spring boot 入门3 SpringBoot深入介绍4 IDEA Spring boot 热部署

application.yml

spring:
    profiles:
        active: prd
---
spring :  
  profiles : prd  
server :
 port : 8081  
---
spring :  
  profiles : dev  
server :  
  port : 8082  
           

将程序打包之后 通过java -jar xx.jar –spring.profiles.active=dev的方式启动不通的配置环境

4) 使用actuator

添加依赖
           
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
           
主要暴露的功能
           
HTTP方法 路径 描述 鉴权
GET /autoconfig 查看自动配置的使用情况 true
GET /configprops 查看配置属性,包括默认配置 true
GET /beans 查看bean及其关系列表 true
GET /dump 打印线程栈 true
GET /env 查看所有环境变量 true
GET /env/{name} 查看具体变量值 true
GET /health 查看应用健康指标 false
GET /info 查看应用信息 false
GET /mappings 查看所有url映射 true
GET /metrics 查看应用基本指标 true
GET /metrics/{name} 查看具体指标 true
POST /shutdown 关闭应用 true
GET /trace 查看基本追踪信息 true

注:此时直接访问会报权限的问题需要在配置文件中配置management.security.enabled=false

5) SpringBoot集成mybatis

引入Mybatis相关联的jar

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.2.0</version>
</dependency>
<!--内存数据库可以直接使用不用配置数据源-->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
           

介绍使用annotation模式的Mybatis调用

编写实体类如下:

import java.io.Serializable;

/**
 * @author Eddú Meléndez
 */
public class City implements Serializable {

    private static final long serialVersionUID = L;

    private Long id;

    private String name;

    private String state;

    private String country;

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getState() {
        return this.state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getCountry() {
        return this.country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Override
    public String toString() {
        return getId() + "," + getName() + "," + getState() + "," + getCountry();
    }

}
           

编写Mapper

@Mapper
public interface CityMapper {

    @Select("select * from city where state = #{state}")
    City findByState(@Param("state") String state);

}
           

在Service层调用Mapper

@Autowired
    private CityMapper cityMapper;
           

Mybatis调用已经完成

6) SpringBoot集成sitemesh

Sitemesh是一种页面装饰技术 :
 它通过过滤器(filter)来拦截页面访问
 根据被访问页面的URL找到合适的装饰模板
 提取被访问页面的内容,放到装饰模板中合适的位置
 最终将装饰后的页面发送给客户端。
           

在pom.xml中添加相应的Jar 配置文件

<dependency>
    <groupId>org.sitemesh</groupId>
    <artifactId>sitemesh</artifactId>
</dependency>
           

编写Filter类

import org.sitemesh.builder.SiteMeshFilterBuilder;
import org.sitemesh.config.ConfigurableSiteMeshFilter;

public class WebSiteMeshFilter extends ConfigurableSiteMeshFilter {

    @Override
    protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
        builder.addDecoratorPath("/*", "/main")
                .addExcludedPath("/main")
                .addExcludedPath("/login")
                .addExcludedPath("/static/*");
    }
}
           

在应用程序入口文件中此处在DemoApplication类中实现Filter注册bean

@Bean
    public FilterRegistrationBean siteMeshFilter(){
        FilterRegistrationBean fitler = new FilterRegistrationBean();
        WebSiteMeshFilter siteMeshFilter = new WebSiteMeshFilter();
        fitler.setFilter(siteMeshFilter);
        return fitler;
    }
           

最后编写如下模板文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TPA-
        <sitemesh:write property='title'/>
    </title>
    <script type="text/javascript" src="${request.contextPath}/static/js/jquery-1.11.1.min.js"></script>
    <script type="text/javascript" src="${request.contextPath}/static/js/msg.js"></script>
    <!-- We support more than 40 localizations -->
    <script type="text/javascript" src="${request.contextPath}/static/js/i18n/grid.locale-cn.js"></script>
    <!-- This is the Javascript file of jqGrid -->
    <script type="text/javascript" src="${request.contextPath}/static/js/jquery.jqGrid.min.js"></script>
    <script type="text/javascript" src="${request.contextPath}/static/js/jqgrid.extend.js"></script>
    <!-- This is the localization file of the grid controlling messages, labels, etc.
    <!-- A link to a jQuery UI ThemeRoller theme, more than 22 built-in and many more custom -->
    <link rel="stylesheet" href="${request.contextPath}/static/css/bootstrap.min.css">
    <link rel="stylesheet" href="${request.contextPath}/static/css/msg.css">
<#--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">-->
    <!-- The link to the CSS that the grid needs -->
    <link rel="stylesheet" type="text/css" media="screen"
          href="${request.contextPath}/static/css/ui.jqgrid-bootstrap.css"/>
    <sitemesh:write property='head'/>
    <script>
        $.jgrid.defaults.width = ;
        $.jgrid.defaults.height = ;
        $.jgrid.defaults.styleUI = 'Bootstrap';
    </script>
    <script type="text/javascript" src="${request.contextPath}/static/js/bootstrap.min.js"></script>
    <style type="text/css">
        .navbar {
            margin-bottom: px;
        }

        /*选择框高度调整*/
        select[multiple], select[size] {
            height: px;
        }
    </style>
</head>
<body>
<div class="container">

    <nav class="navbar navbar-default">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
            <#--<a class="navbar-brand" href="/bbs/bbs/index">-->
            <#--<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1880"><path d="M832.299957 714.965621c-71.047126 88.067778-148.2126 70.077032-148.2126 70.077032 77.615729-65.686025 74.107835-233.597269 74.107835-233.597269 56.979736 6.564509 74.104765 93.439112 74.104765 93.439112 2.635013 53.857629 148.21567 93.439112 148.21567 93.439112C887.304711 721.78698 832.299957 714.965621 832.299957 714.965621zM513.173732 467.12086c0 0-26.707268-15.610536-21.554922-82.356706 0 0 43.672662-370.594433 237.145072-313.196165 0 0 128.243803 88.283696-21.580504 292.610314C707.182354 364.178303 570.780755 504.72634 513.173732 467.12086zM560.578392 504.72634c31.834033 103.172801-49.409316 210.239282-49.409316 210.239282-95.057983 32.713053-67.633377-56.756655-67.633377-56.756655 58.984393-61.013609 42.930765-130.125663 42.930765-130.125663C512.189312 506.013659 560.578392 504.72634 560.578392 504.72634zM214.740806 668.246577c0 0-15.826454-68.054979 9.243525-99.791797 0 0 19.540032 53.137221 64.86431 6.345522 0 0 13.948687-61.868069-50.226938-47.768957 0 0 21.086248-69.096704 66.274426-103.007025-82.760912-100.30652-238.370992-82.821287-238.370992-82.821287-51.842739-30.236652 0-46.715975 0-46.715975 135.454018-0.991584 222.324528 93.439112 222.324528 93.439112-23.989367-126.739543-148.21567-163.520237-148.21567-163.520237-39.818891-48.290843 17.485233-35.68371 17.485233-35.68371 126.141932 81.534991 149.874449 190.310394 154.345274 230.244918 20.531616-12.791327 45.414329-18.281365 75.196633-7.67889 0 0 156.796092 73.606415-24.702612 256.95935C362.956476 668.246577 246.483764 776.989233 214.740806 668.246577zM706.990996 513.219781c30.182416 116.948549-22.903639 201.74584-22.903639 201.74584-59.500139 125.21891-148.21567 46.719044-148.21567 46.719044 93.910856-94.708012 98.807377-256.95935 98.807377-256.95935C675.925467 502.981602 706.990996 513.219781 706.990996 513.219781z" p-id="1881"></path></svg>-->
            <#--Beetl-BBS-->
            <#--</a>-->
            </div>

            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li id="personManagerLi"><a href="${request.contextPath}/manager/classify">类型管理</a></li>
                    <li id="employeeManagerLi"><a href="${request.contextPath}/system/employee">用户管理</a></li>
                    <li id="roleManagerLi"><a href="${request.contextPath}/system/role">角色管理</a></li>
                    <li id="resourceManagerLi"><a href="${request.contextPath}/system/resource">资源管理</a></li>
                    <li id="resourceManagerLi"><a href="${request.contextPath}/system/method">方法管理</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">板块 <span
                                class="caret"></span></a>
                        <ul class="dropdown-menu" role="menu">
                            <li><a href="#">AAA </a></li>
                            <li><a href="#">BBB </a></li>
                            <li><a href="#">CCC </a></li>
                        </ul>
                    </li>
                </ul>
                <form class="navbar-form navbar-left">
                    <div class="form-group">
                        <input type="text" class="form-control" id="keyword" placeholder="关键字搜索">
                    </div>
                    <button type="button" class="btn btn-default" id="serach-btn">搜索</button>
                </form>

                <form id="logoutForm" action='${request.contextPath}/logout' method='post'>
                </form>
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a href="javascript:$('#logoutForm').submit();" data-toggle="modal"><i class="fa fa-sign-in"></i> 退出</a>
                    </li>
                    <li><a href="#reg-dialog" data-toggle="modal"><i class="fa fa-user-plus"></i> 注册</a></li>

                </ul>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <sitemesh:write property='body'/>
</div>
</body>
</html>
           

7) SpringBoot单元测试

Controller层测试如下使用MockMvc

@RunWith(SpringRunner.class)
@SpringBootTest
public class TpaSecurityApplicationTests {
    @Autowired
    private RoleController roleController;

    private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders.standaloneSetup(roleController).build();
    }

    @Test
    public void contextLoads() throws Exception {

        RequestBuilder request = null;

        request = get("/system/role/1");
        mvc.perform(request)
                .andExpect(status().isOk());

        request = put("/system/role/1")
                .param("name", "测试终极大师");
        // 4、put修改id为1的user
        mvc.perform(request);

    }

}
           

services mapper 层测试更简单

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

    @Autowired
    private CityMapper cityMapper;
    @Test
    public void contextLoads() {
    }

    @Test
    public void findByStateTest() {
        City city = cityMapper.findByState("CA");
        assertThat(city.getName()).isEqualTo("San Francisco");
        assertThat(city.getState()).isEqualTo("CA");
        assertThat(city.getCountry()).isEqualTo("US");
    }
}
           

4 IDEA Spring boot 热部署

1) CTRL + SHIFT + A –> 查找make project automatically –> 选中 此处可以更新页面展示文件

2) 使用spring-boot-1.3开始有的热部署功能

加maven依赖

<dependency>  
      <groupId>org.springframework.boot</groupId>  
      <artifactId>spring-boot-devtools</artifactId>  
      <optional>true</optional>  
</dependency>  
           

开启热部署

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
            </configuration/>
        </plugin>
    </plugins>
</build>
           

注:此时热部署更改文件class文件之后整个项目重启,时间可能比较长但是启动比较彻底

3) 使用springreload插件重启,

project 节点下添加:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>springloaded</artifactId>
                    <version>1.2.6.RELEASE</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
           

注:修改class类时热部署,不会整个项目重启,修改比较快速,但是需要mvn spring-boot:run启动项目才可以热部署

继续阅读