Skip to content

Lyon-NEU/Spring-Boot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Spring-Boot

连接数据库

通过外部配置文件中的 spring.datasource.*.配置DataSource. 例如可以在 application.properties文件中如下配置 spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

配置pom

第一次配置的时候,编译成功,运行时总是提示Bean示定义nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field:。原先添加的依赖为

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>

重新修改为以下配置后,运行正确

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

日志

Spring Boot 是通过调用Commons Logging来实现内部日志功能。用户可根据自身需要来实现底层的接口。默认的配置为Java Util Logging, Log4J,Log4J2Logback 如果选择Starter POMS,系统会默认选择Logback

日志格式

默认的日志输出格式像下面这样:

2014-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698  INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702  INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to:

Spring Data JPA

@Entity
public class User{
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    private String firstName;
    private String lastName;

    protected User(){}

    public User(String firstName,String lastName){
        this.firstName=fristName;
        this.lastName=lastName;
    }

    @Override
    public String toString(){
        return String.format(
                "User[id=%d, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }
}
  • id 作为惟一标识符, @GeneratedValue(strategy=GenerationType.AUTO)表明它是一个自增字段
  • firstNamelastName 映射为同名字段
    import java.util.List;

    import org.springframework.data.repository.CrudRepository;

    public interface UserRespository extends CrudRepository<User,Long>{
        List<User> findByLastName(String lastName);
    }

CrudRepository 已经包含了save,delete,findOne(),findALl()等预定义方法,可以根据命名约定来扩展。

外部配置

Spring-Boot支持扩展配置,所以可以在不同的环境下运行相同的代码。可以通过 属性文件YAML文件和 环境变量以及 命令行参数来配置。属性值可以通赤@Value直接注入组件当中。

Spring-Boot按如下顺序执行:

  • 命令行参数
  • Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)
  • JNDI attributes from java:comp/env.
  • Java System properties (System.getProperties()).
  • 系统环境变量
  • A RandomValuePropertySource that only has properties in random.*.
  • Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)
  • Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)
  • Application properties outside of your packaged jar (application.properties and YAML variants).
  • Application properties packaged inside your jar (application.properties and YAML variants).
  • @PropertySource annotations on your @Configuration classes.
  • Default properties (specified using SpringApplication.setDefaultProperties)

例,如下注入name属性

    import org.springframework.stereotype.*;
    import org.springframework.beans.factory.annotation.*;

    @Component
    public class MyBean{
        @Value("${name}")
        private String name;

        //...
    }

在类路径(如,在jar里面)建立文件application.propertites,给name设置一个正确的默认值.也可以在jar文件外部,这样会覆盖内部的。同样同过命令行也可实现(java -jar app.jar --name="Spring")

配置随机值

在进行安全类或测试的时候,可以考虑通过RandomValuePropertySource来注入随机值。支持整型、长整型、字符串等。

my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

应用属性文件

SpringApplication按照以下的顺序来加载application.propertites文件,并将它们添加到Spring的环境当中:

  1. 当前目录里的/config子目录
  2. 当前目录
  3. config包下的类路径
  4. 根路径

文件中的占位符

application.propertites中定义的值在会先在已存在的环境变量中查找,所以你可以引用前面定义的变量。

app.name=MyApp
app.description=${app.name} is a Spring Boot application

使用YAML

加载YAML

Spring Framework提供了两种方便的方式来加载YAML文件,YamlPropertiesFactoryBean将YAML看作Properties ,而 YamlMapFactoryBean 将YAML看作是一个Map. 例,下面的YAML文件

environments:
    dev:
        url: http://dev.bar.com
        name: Developer Setup
    prod:
        url: http://foo.bar.com
        name: My Cool App

将会被转换为下面的属性:

environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App

可以通过Spring的DataBinder(@ConfigurationPropertites)来绑定值。

    @ConfigurationProperties(prefix="my")
    public class Config{
        private List<String> servers=new ArraList<String>();

        public List<String> getServers(){
            return this.servers;
        }
    }

Spring Web MVC

Spring Web MVC框架是一个富'model view controller'网页框架,可以通过创建@Controller或者@RestController组件来处理接收到的HTTP请求。通过使用@RequestMapping标记来将controller里的方法映射成HTTP。下面是一个典型的使用@RestContoller来解析JSON数据例子:

@RestContoller
@RequestMapping(value="/users")
public class MyRestController{

    @RequestMapping(value="/{user}",method=RequestMethod.GET)
    public User getUser(@PathVariable Long user){
        //...
    }
    @RequestMapping(value="/{user}/customers",method=RequestMethod.GET)
    List<Customer> getUserCustomers(@PathVariabel Long user){
        //..
    }
    @RequestMapping(value="/{user}",method=RequestMethod.DELETE)
    public User deleteUser(@PathVariable Long user){
        //...
    }
}

Spring MVC是Spring核心框架的一部分,可以参考官方引用文档。

Spring MVC自动配置

HttpMessageConverters

Spring MVC使用HttpMessageConverter接口转换HTTP请求的响应消息,对象可以自动转换为JSON或者XML,字符串默认以UTF-8编码。 可以通过使用HttpMessageConverter类添加或修改:

import org.springframework.boot.autoconfigure.web.HttpMessageConveters;
import org.springframework.boot.context.annotation.*;
import org.springframework.http.conveter.*;

@Configuration
public class MyConfiguration{

    @Bean
    public HttpMessageConverters customConverters(){
        HttpMessageConverter<?> additional=...
        HttpMessageConverter<?> another=...
        return new HttpMessageConverter(additional,another);
    }
}

上下文件中的任何HttpMessageConverter组件都会添加到Converter列表中。

##静态内容 Spring Boot默认会从/static (或者/public/resources/META-INF/resources)目录加载静态内容。Spring Boot使用Spring MVC里的ResourceHttpRequestHandler来实现该功能,所以用户可自己实现WebMvcConfigurerAdapter并且重载addResourceHandlers方法。

错误处理

Spring Boot默认情况下使用/error映射来处理错误,它在servelet容器里注册为一个全局的错误页。在电脑客户端,它生成一个JSON格式的信息,包括HTTP状态码和异常信息;在浏览器端它返回一个Whitelabel错误视图(可以通过自定义一个视图来解析error)。通过实现ErrorController接口可以完全替代它,然后注册一个该类型的bean,或者简单的添加一个ErrorAttributes类型的bean。

通过@ControllerAdvice可以自定义JSON数据文档:

@ControllerAdvice(basePackageClasses=FooController.class)
public class FooControllerAdvice extends ResponseEntityExceptionHandler{

    @ExceptionHandler(YourException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerExcepion(HttpServletRequest request,Throwable ex){
        HttpStatus status=getStatus(request);
        return new ResponseEntity<>(new CustomErrorType(status.value(),ex.getMessage()),status);
    }

    private HttpStatus getStatus(HttpServletRequest request){
        Integer statusCode=(Integer)request.getAttribute("javax.servlet.error.status_code");
        if(statusCode==null){
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }
}

上面的例子中,如果 YourException 被和FooController同一个包下面的controller抛出, a json representation of the CustomerErrorType POJO 会替代 ErrorAttributes 的表达形式

如果你想更多的特定条件错误,嵌套的servlet容器支持一种均匀的 Java DSL 来自定义 the error handling. Assuming that you have a mapping for /400:

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer(){
    return new MyCustomizer();
}

// ...

private static class MyCustomizer implements EmbeddedServletContainerCustomizer {

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        container.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
    }

}

Testing

Spring Boot提供了很多有用的测试工具。spring-boot-starter-test POM包含Spring Test,JUnit,HamCrest和Mockito依赖。

Spring应用测试

依赖注入的一个最主要的优势是可以让你的单元测试代码更简单。可以通过new操作符来实例化对象而不需要包含Spring,也可以使用mock 对象而非真实的对象。 通常你可能不仅需要单元测试或start包含的测试(事实上只是包含ApplicationContext)。在布署应用或不需要连接其它基础设备的条件下进行集成测试是非常有用的。 Spring Framewrok包含了一个详细的集成测试模块,可以直接声明依赖org.springframework:spring-test,或使用spring-boot-starter-test

Spring Boot应用测试

一个Sping Boot应用就是一个Spring ApplicationContext,所以几乎不需做任何特殊的操作。 Spring Boot提供@SpringApplicationConfiguration作为标准的spring-test @ContextConfiguration标记的替代。

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SampleDataJpaApplication.class)
public calss CityRepositoryIntegrationTests{

    @Autowired
    CityRepository repository;

    //..
}

OutputCaptuer

OutputCapture是JUnit的一个Rule,可以用来捕获System.outSystem.err。只需简单的声明captuer为@Rule,然后使用toString()作为assertions:

import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.OutputCapture;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

public class MyTest{

    @Rule
    public OutputCaptuer capture=new OutputCapture();

    @Test
    public void testName() throws Exception{
        System.out.println("Hello World!");
        assertThat(capture.toString(),containString("World"));
    }
}

TestRestTemplate

TestRestTemplate是一个Spring RestTemplate的一个简单子类,非常方便集成测试。你可以获取一个vanilla模块或者发送基本HTTP认证(用户名和密码),无论哪种方式,模板都会以一个test-friendly方式:not following redirects(所以你可以assert 响应定位),忽略cookies,也不会在服务器端抛出异常。

public class MyTest{

    RestTemplate template=new TestRestTemplate();

    @Test
    public void testRequest() throws Exception{
        HttpHeaders headers=template.getForEntity("http://myhost.com",String.class).getHeaders();
        assertThat(headers.getLocation().toString(),containsString("myotherhost"));
    }
}

访问应用参数

可以通过注入一个org.springframework.boot.ApplicationArguments bean来访问传递给SpringApplication.run(...)的参数,ApplicationArguments接口提供了原始String[]参数,也可以使用optionnon-option参数:

import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;

@Component
public class MyBean{

    @Autowired
    public MyBean(ApplicationArguments args){
        boolean debug=args.containsOption("debug");
        List<String>files=args.getNonOptionArgs();
        //if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
    }
}

23.7 使用ApplicationRunner或CommandLineRunner

如果在SpringApplication启动后需要运行一些代码,可以实现ApplicationRunner或者CommandLineRunner接口。这两个接口以相同的方式担供一个run方法,它会仅在SpringApplication.run(...)完成前调用。

import org.springframework.boot.*;
import org.springframework.stereotype.*;

@Component
public class MyBean implements CommandLineRuuner{

    public void run(String...args){
        //Do something...
    }
}

33. 消息

Spring Framework提供了大量的方法来集成消息系统,可以简单的调用JmsTemplate来访问JMS API,也可以自定义异步接收消息。Spring AMQP提供了一个相似的特征集"Advanced Message Queuing Protocal",Spring Boot支持RabbitTemplate自动配置选项.

33.1 JMS

javax.jms.ConnectionFactory接口定义了一个标准的创建javax.jms.Connection的方法,用来同JMS broker交互。尽管Spring需要一个ConnectionFactory来使用JMS,但是通常来说你并不需要直接使用,你可以使用更高级的消息抽象来替换。

33.1.1 ActiveMQ 配置

当在系统路径中检测到ActiveMQ时,Spring Boot就配置一个ConnectionFactory。如果代理存在,一个嵌入的代理启动,并且自动配置(除非通过配置来改变代理的URL) 通过外部属性来对ActiveMQ进行配置,以spring.activemq.*的形式,例如,你可以在application.properties中按如下定义:

spring.activemq.broker-url=tcp://192.168.1.210:9876
spring.activemq.user=admin;
spring.activemq.password=secret;

默认情况下,ActiveMQ会自动创建一个目标,如果当前不存在的话。

About

spring boot

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors