前言

spring Boot是Spring社区较新的一个项目。该项目的目的是帮助开发者更容易的创建基于Spring的应用程序和服务,让更多人的人更快的对Spring进行入门体验,让Java开发也能够实现Ruby on Rails那样的生产效率。为Spring生态系统提供了一种固定的、约定优于配置风格的框架。

Spring Boot特性

Spring Boot具有如下特性:

  • 为基于Spring的开发提供更快的入门体验
  • 开箱即用,没有代码生成,也无需XML配置。同时也可以修改默认值来满足特定的需求。
  • 提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等。
  • Spring Boot并不是不对Spring功能上的增强,而是提供了一种快速使用Spring的方式

官方文档:http://docs.spring.io/spring-boot/docs/current/reference/html/index.html

https://start.spring.io/是官方的提供的,可以快速生成空的项目文件,免去了配置文件等初始化流程。

Spring Boot 实例demo

环境准备:

  • 一个称手的文本编辑器(例如Vim、Emacs、Sublime Text)或者IDE(Eclipse、Idea Intellij)
  • Java环境(JDK 1.7或以上版本)
  • Maven 3.0+(Eclipse和Idea IntelliJ内置,如果使用IDE并且不使用命令行工具可以不安装)

目录结构

有Spring基础的接触Spring Boot应该很快就可以上手的,首先通过上面提供的官方的初始化一个项目,如下是本实例demo是的一个目录结构(环境是IntelliJ):

这里写图片描述

java目录:用来存放java文件,例如MVC模式的话,存放相关代码

resources目录有static和templates两个子目录,其中static目录存放css/js/images等文件,templates目录存放模板文件,例如xx.vm(Velocity的文件是.vm,Velocity的相关介绍可以参见之前博客http://blog.csdn.net/megustas_jjc/article/details/60596358

实例demo

程序入口

首先来创建src/main/java/ToutiaoApplication.java:

@SpringBootApplication
public class ToutiaoApplication {

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

程序的入口:SpringApplication.run(Application.class, args),SpringApplication是Spring Boot框架中描述Spring应用的类,它的run()方法会创建一个Spring应用上下文(Application Context)。另一方面它会扫描当前应用类路径上的依赖,如果Spring Boot判断这是一个Web应用,会启动一个内嵌的Servlet容器(默认是Tomcat)用于处理HTTP请求。

@SpringBootApplication:
Spring Boot提供一个方便的 @SpringBootApplication 选择。该 @SpringBootApplication 注解等价于以默认属性使用 @Configuration+@EnableAutoConfiguration+@ComponentScan

@Configuration :

定义一个配置类,用@Configuration注解该类,等价于XML中配置beans;用@Bean标注方法等价于XML中配置bean

public class SpringConfig {  

    @Bean  
    public Piano piano(){  
        return new Piano();  
    }  
    @Bean(name = "counter")   
    public Counter counter(){  
        return  new Counter(12,"Shake it Off",piano());  
    }  
} 

@EnableAutoConfiguration:启动Spring MVC

@ComponentScan:启用组件扫描

实现Hello World显示

在controller目录下创建一个IndexController 类(之后的方法除特殊说明,否则都是IndexController类中的方法),

@Controller
public class IndexController {
    @RequestMapping(path = {"/","/index"})
    @ResponseBody
    public String index(HttpSession session){
        return "Hello World" ;
    }
}

运行我们的Application文件,右键Run As -> Java Application,之后打开浏览器输入地址:http://127.0.0.1:8080/(或者http://127.0.0.1:8080/ index) 就可以看到Hello world。

@Controller :基于@Component注解,表明是控制类组件,辅助实现组件扫描,组件扫描会自动找到@Controller注解对应的类,并将其声明为Spring应用上下文的一个bean

@RequestMapping:@RequestMapp(value=”/”,method),value值属性指定了这个方法所要处理的请求路径,method属性细化了它所处理的HTTP方法(GET或者POST),例如@RequestMapping(value = "/login", method = RequestMethod.POST)

@RequestBody绑定请求对象,Spring会帮你进行协议转换,将Json、Xml协议转换成你需要的对象。
@ResponseBody可以标注任何对象,由Srping完成对象——协议的转换。
在SpringMVC中,可以使用@RequestBody和@ResponseBody两个注解,分别完成请求报文到对象和对象到响应报文的转换,底层这种灵活的消息转换机制,就是Spring3.x中新引入的HttpMessageConverter即消息转换器机制。

获取请求中信息

    //value与path都是别名,实质上是一样的
    @RequestMapping(value = {"/profile/{groupId}/{userId}"})
    @ResponseBody
    //127.0.0.1:8080/profile/12/33?key=xx&type=33
    //不要混淆PathVariable与RequestParam
    public String profile(
    @PathVariable("groupId") String groupId,
    @PathVariable("userId") int userId,
    @RequestParam(value = "key",defaultValue = "megustas") String key,
    @RequestParam(value = "type",defaultValue = "1") int type) {
        return String.format("GID{%s},UID{%d},KEY{%s},TYPE{%d}",groupId,userId,key,type);
    }

例如//127.0.0.1:8080/profile/12/33?key=xx&type=33,

这里写图片描述

String.format():Java字符串格式化-静态方法String.format()

@Pathvariable:
当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上

@RequestParam:获取请求参数

模板渲染

在之前所有的@RequestMapping注解的方法中,返回值字符串都被直接传送到浏览器端并显示给用户。但是为了能够呈现更加丰富、美观的页面,我们需要将HTML代码返回给浏览器,浏览器再进行页面的渲染、显示。

一种很直观的方法是在处理请求的方法中,直接返回HTML代码,但是这样做的问题在于——一个复杂的页面HTML代码往往也非常复杂,并且嵌入在Java代码中十分不利于维护。更好的做法是将页面的HTML代码写在模板文件中(此处使用Velocity模板语言),渲染后再返回给用户。为了能够进行模板渲染,需要将@RestController改成@Controller:

    //返回值不再是ResponseBody,返回值是一个模板,模板存放于resources/templates中
    @RequestMapping(value = {"/vm"})
    //后端与渲染之间铰链的一个数据模型Model,通过Model向前台视图传递参数,Model中存入的数据在Velocity中直接使用
    public String news(Model model){
        model.addAttribute("value1", "vv1");
        List<String> colors = Arrays.asList(new String[]{"RED", "GREEN", "BLUE"});

        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < 4; ++i) {
            map.put(String.valueOf(i), String.valueOf(i * i));
        }
        model.addAttribute("colors", colors);
        model.addAttribute("map", map);
        //传递自定义对象
        model.addAttribute("user",new User("Megustas"));
        return "news";//news.vm
    }

在上述例子中,返回值”news”并非直接将字符串返回给浏览器,而是寻找名字为news的模板进行渲染,news.vm文件存放于resources/templates目录下(vm源码见博客最后)。

这里写图片描述

request/response

一次网页请求中,通过request获取它的所有数据

    @RequestMapping(value = {"/request"})
    @ResponseBody
    public String request(HttpServletRequest request,
                          HttpServletResponse response,
                          HttpSession session){
        //获取Http请求的头文件
        StringBuilder sb = new StringBuilder();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()){
            String name = headerNames.nextElement();
            sb.append(name + ":" + request.getHeader(name) + "<br>");
        }

        for(Cookie cookie : request.getCookies()){
            sb.append("Cookie");
            sb.append(cookie.getName());
            sb.append(":");
            sb.append(cookie.getValue());
            sb.append("<br>");
        }

        sb.append("getMethod:" + request.getMethod()+ "<br>");
        sb.append("getPathInfo:" + request.getPathInfo()+ "<br>");
        sb.append("getQueryString:" + request.getQueryString()+ "<br>");
        sb.append("getRequestURI" + request.getRequestURI());

        return sb.toString();
    }

这里写图片描述

StringBuilder:
String对象是不可改变的。每次使用 System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的 String对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用System.Text.StringBuilder类。例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder类可以提升性能。

Enumeration:
Enumeration接口作用和Iterator类似,提供了遍历元素的功能,其中只定义了两种方法:

boolean hasMoreElements():测试Enumeration对象中是否包含元素,如果有返回true,则表示至少包含一个元素

Object nextElement():如果Enumeration对象还有元素,返回对象的下一个元素,否则抛出NoSuchElementException

request.getQueryString():
request.getQueryString()就是获取查询字符串
即请求?后面的就是QueryString,例如127.0.0.1:8080/request?type=2&&k=xx中,QueryString为type=2&&k=xx,RequestURI为/request

也可以通过HttpServletResponse response将更多数据写回


    @RequestMapping(value = {"/response"})
    @ResponseBody
    public String response(@CookieValue(value="nowcoderid",defaultValue = "a") String nowcoderId,
                           @RequestParam(value = "key", defaultValue = "key") String key,
                           @RequestParam(value = "value", defaultValue = "value") String value,
                           HttpServletResponse response){
        response.addCookie(new Cookie(key,value));
        response.addHeader(key,value);
        return "NowCoderId From Cookie:" + nowcoderId;

    }

这里写图片描述

127.0.0.1:8080/response : NowCoderId From Cookie:a,此时为默认值

127.0.0.1:8080/response?key=nowcoderid&value=22:NowCoderId From Cookie:22

重定向与error

301:永久转移
302:临时转移

首先介绍两种重定向的方式,第二种更简单直接一些:

    @RequestMapping("/redirect/{code}")
    public RedirectView redirect(@PathVariable("code") int code){
        RedirectView red = new RedirectView("/",true);//通过/跳转到首页
        if(code == 301){
            red.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
        }
        return red;
    }
     //一种简单方式的跳转
     @RequestMapping("/redirect/{code}")
     public String redirect(@PathVariable("code") int code,HttpSession session){
        session.setAttribute("msg","Jump from redirect.");
        return "redirect:/";
     }

通过自定义的方式捕获error:

    @RequestMapping("/admin")
    @ResponseBody
    //可以通过required=false或者true来要求@RequestParam配置的前端参数是否一定要传,required=false表示不传的话,会给参数赋值为null,required=true就是必须要有
    public String admin(@RequestParam(value = "key",required = false) String key){
        if("admin".equals(key)){
            return "hello admin";
        }
        throw new IllegalArgumentException("Key 错误");
    }
    //好处是可以用统一的页面处理问题,例如baidu.com/megustas之类的都会统一跳转到一个页面:很抱歉,您要访问的页面不存在
    @ExceptionHandler()
    @ResponseBody
    public String error(Exception e){
        return "error:" + e.getMessage();
    }

这里写图片描述

源码可以从https://coding.net/u/TwistFate/p/SpringBoot/git下载

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐