美文网首页首页投稿(暂停使用,暂停投稿)
从0开始编写一个spring boot 应用

从0开始编写一个spring boot 应用

作者: yubang | 来源:发表于2017-06-21 18:18 被阅读1040次

    为什么要使用spring boot?

    • 入门简单,无需编写大量的xml文件来配置应用
    • 内置tomcat,可以生成直接运行的独立jar文件
    • 简化了spring框架一些繁琐的开发方式,提供很多与第三方库的结合

    使用eclipse新建一个spring boot工程

    1.先在eclipse官网下载一个eclipse EE
    2.new -> Maven Project

    新建maven项目

    3.填写项目信息

    选择项目路径 选择quickstart 填写项目默认包名

    ** 安装spring boot依赖 **
    在pom.xml文件添加一点点东西(保存的时候eclipse会自动下载依赖),整个文件如下:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>demo</groupId>
        <artifactId>demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>demo</name>
        <url>http://maven.apache.org</url>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.4.RELEASE</version>
        </parent>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
        </dependencies>
    </project>
    
    

    路由配置(输出hello world)

    在默认生成的App.java文件修改成下面的代码:

    package demo.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
    import org.springframework.boot.web.support.SpringBootServletInitializer;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    
    @Controller
    @EnableAutoConfiguration
    public class App  extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer {
        
        @RequestMapping("/")
        @ResponseBody
        String home() {
            return "Hello World!";
        }
        
        public void customize(ConfigurableEmbeddedServletContainer container) {  
            container.setPort(8000);  
        }  
        
        public static void main( String[] args ){
            SpringApplication.run(App.class, args);
        }
    }
    
    

    然后我们运行这个文件,在浏览器访问 http://127.0.0.1:8000/ 即可看到效果。

    我们来分析这个文件做了什么:

    • 其中main方法的代码就是启动spring boot应用

    • 继承SpringBootServletInitializer 类实现EmbeddedServletContainerCustomizer 接口编写customize方法其实是为了修改spring boot应用监听的端口

    • 类的两个修饰器,@Controller是声明是一个控制器类,@EnableAutoConfiguration大概是自动加载一些bean

    • 我们输出Hello World!的方法也有两个修饰器,@RequestMapping("/")是绑定路由,就是浏览器域名端口后面的一段字符串(不包括get参数),@ResponseBody表示输出字符串到浏览器

    也许你会问,我如何限制get或者post方法请求该方法?

    @RequestMapping(value="/", method=RequestMethod.POST)
        @ResponseBody
        String home() {
            return "Hello World!";
        }
    
    • get请求: RequestMethod.GET

    • post请求:RequestMethod.POST

    • put请求: RequestMethod.PUT

    • delete请求: RequestMethod.DELETE

    现在可以限制请求方式了,但是我想正则匹配路由又该如何处理呢?

    @RequestMapping("/test/{a}/*/{b:\\d+}")
        @ResponseBody
        public String index(@PathVariable int b, @PathVariable String a){
            System.out.println(a);
            System.out.println(b);
            return "test!";
        }
    

    请求 http://127.0.0.1:8000/test/cbd/qwe/123 就可以看到效果!

    • {XXX}来匹配一个任意字符串
    • {xxx:正则表达式}来匹配符合规则的字符串
    • *匹配任意字符串
    • @PathVariable 修饰器把{X}的内容注入方法的参数里面

    GET,POST参数获取

    @RequestMapping("/test")
        @ResponseBody
        public String test(HttpServletRequest request){
            return request.getParameter("a");
        }
    

    使用HttpServletRequest 对象的getParameter方法即可获取get或者post参数,如果参数不存在则返回null

    输出结果设置headers

    @RequestMapping(value="/test2", produces="text/plain")
        @ResponseBody
        public String test2(HttpServletResponse response){
            response.setHeader("own", "m");
            return "ok";
        }
    
    • 修改content-type需要在修饰器的produces参数指定

    • 自定义header调用setHeader方法即可

    ** 上传和下载文件 **

    先看demo代码:

    
    @Bean
        public MultipartConfigElement multipartConfigElement() {
            MultipartConfigFactory factory = new MultipartConfigFactory();
            factory.setMaxFileSize("128KB");
            factory.setMaxRequestSize("128KB");
            return factory.createMultipartConfig();
        }
    
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
        @ResponseBody
        public String upload(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws IOException {
            response.setContentType("application/octet-stream");
            OutputStream os = response.getOutputStream();
            os.write(file.getBytes());
            return "upload!";
        }
    

    其实很简单,接收文件只要在参数加上@RequestParam("file") MultipartFile file。"file"是post文件的变量名字

    下载文件,先拿输出response.getOutputStream();。当然记得要设置content-type

    模板渲染

    这里使用了Thymeleaf模板引擎,其他模板引擎实在搜不出可运行方案。

    第一步添加依赖:

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

    第二步,在src/main/resources/templates文件夹编写模板文件,以.html结尾

    第三步,编写代码返回模板

    package demo.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class Debug {
    
        @RequestMapping("/index")
        public String index2(){
            return "web";
        }
        
    }
    
    

    注意返回的字符串不需要加上.html。

    静态文件处理

    新建一个类(这里是StaticConfig),继承WebMvcConfigurerAdapter类,重写addResourceHandlers方法,代码如下:

    package demo.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    public class StaticConfig extends WebMvcConfigurerAdapter {
        
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {
            resourceHandlerRegistry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
            super.addResourceHandlers(resourceHandlerRegistry);
        }
        
    }
    

    静态文件放在src/main/resources/static文件夹即可

    当然为了让配置生效,我们需要在主类增加注解@ComponentScan("demo.config"),demo.config换成你新建类的包名

    允许跨域请求

    只需要往入口类添加下面代码:

    // 允许跨域请求
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**").allowedOrigins("*");
                }
            };
        }
    

    数据库操作

    1.第一步当然是引入依赖咯,往pom.xml里面添加下面代码:

    <!-- 与数据库操作相关的依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
            <!-- 使用数据源 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.0.14</version>
            </dependency>
            <!-- mysql -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <!-- mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.2.8</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>1.2.2</version>
            </dependency>
    

    2.新建一个类用于配置数据库信息

    package demo.config;
    
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    @Configuration
    @PropertySource(value="classpath:/demo/config/db_local.properties", ignoreResourceNotFound=true)
    public class MyBatisConfig {
        
        @Value("${driverClassName}")
        private String driverClassName;
        
        @Value("${url}")
        private String url;
        
        @Value("${db_username}")
        private String username;
        
        @Value("${password}")
        private String password;
        
        /**
         * 创建数据源
         * @Primary 该注解表示在同一个接口有多个实现类可以注入的时候,默认选择哪一个,而不是让@autowire注解报错 
         */
        @Bean
        //@Primary
        public DataSource getDataSource() throws Exception{
            Properties props = new Properties();
            props.put("driverClassName", this.driverClassName);
            props.put("url", this.url);
            props.put("username", this.username);
            props.put("password", this.password);
            return DruidDataSourceFactory.createDataSource(props);
        }
    
        /**
         * 根据数据源创建SqlSessionFactory
         */
        @Bean
        public SqlSessionFactory sqlSessionFactory(DataSource ds) throws Exception{
            SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
            fb.setDataSource(ds);//指定数据源(这个必须有,否则报错)
            //下边两句仅仅用于*.xml文件,如果整个持久层操作不需要使用到xml文件的话(只用注解就可以搞定),则不加
            //fb.setTypeAliasesPackage("com.xxx.firstboot.domain");//指定基包
            //fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));//指定xml文件位置
            
            return fb.getObject();
        }
        
    }
    
    

    当然入口类记得加上扫描(@ComponentScan("demo.config"))

    上面数据库密码那些是读取了配置文件所以新建一个配置文件(配置文件读取参考下文说明)

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/map?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
    db_username=root
    password=root
    

    3.定义操作数据表的接口

    import java.util.List;
    
    import org.apache.ibatis.annotations.Select;
    
    public interface SpecialtyMapper {
        
        @Select("select * from specialty where province = #{province};")
        List<demo.dao.SpecialtyDao> getSpecialtyList(String province);
        
    }
    
    

    当然,我们要在入口类用修饰器扫描这些模型类,@MapperScan("demo.mapper")

    trip.footprint.dao.SpecialtyDao只是一个普通的java类,用于存储查询到的数据

    package demo.dao;
    
    import java.sql.Timestamp;
    
    public class SpecialtyDao {
    
        private int id;
        private String province;
        private String title;
        private String img;
        private Timestamp create_time;
        private Timestamp update_time;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getProvince() {
            return province;
        }
    
        public void setProvince(String province) {
            this.province = province;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getImg() {
            return img;
        }
    
        public void setImg(String img) {
            this.img = img;
        }
    
        public Timestamp getCreate_time() {
            return create_time;
        }
    
        public void setCreate_time(Timestamp create_time) {
            this.create_time = create_time;
        }
    
        public Timestamp getUpdate_time() {
            return update_time;
        }
    
        public void setUpdate_time(Timestamp update_time) {
            this.update_time = update_time;
        }
    
    }
    
    

    4.在controller中使用

    package demo.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class Debug {
        
        @Autowired
        private demo.mapper.SpecialtyMapper specialtyMapper;
        
        @RequestMapping("/abc")
        @ResponseBody
        public String index(){
            specialtyMapper.getSpecialtyList("广东省");
            return "ok";
        }
        
    }
    
    

    session放于redis

    新建一个java类

    package trip.footprint.config;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
    import org.springframework.session.data.redis.config.ConfigureRedisAction;
    import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
    
    @Configuration
    @EnableRedisHttpSession
    @PropertySource(value = "classpath:/trip/footprint/config/redis_bae.properties")
    public class SessionConfig {
        @Value("${redisHost}")
        private String redisHost;
    
        @Value("${redisPort}")
        private int redisPort;
    
        @Value("${redisPassword}")
        private String redisPassword;
    
        @Value("${redisDb}")
        private int redisDb;
        
        @Bean
        public static ConfigureRedisAction configureRedisAction() {
            return ConfigureRedisAction.NO_OP;
        }
        
        @Bean
        public JedisConnectionFactory connectionFactory() {
            JedisConnectionFactory factory = new JedisConnectionFactory();
            factory.setHostName(redisHost);
            factory.setPort(redisPort);
            if(redisDb!=-1){
                factory.setDatabase(redisDb);
            }
            if (!redisPassword.equals("")) {
                factory.setPassword(redisPassword);
            }
            return factory;
        }
    
    }
    

    然后记得用@ComponentScan("demo.config")来扫描加载

    由于代码读取配置文件,所以新建一个配置文件

    redisHost=127.0.0.1
    redisPort=6379
    redisPassword=
    redisDb=0
    

    controller分离成多个文件

    其实每一个controller都是一个java类,只是类上面有一个修饰器@Controller或者@RestController。当然记得用@ComponentScan("xxx.xxx")来扫描加载

    依赖注入

    首先想把类A作为一个变量注入类B,就需要用修饰器@ComponentScan扫描类A和类B的包,同时类A要在类上面加入修饰器@Component,类B变量上面添加修饰器 @Autowired。

    类A代码:

    package demo.data;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class A {
        
        public String data = "good!";
        
    }
    
    

    类B代码:

    package demo.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class Debug {
        
        @Autowired
        private demo.mapper.SpecialtyMapper specialtyMapper;
        
        @Autowired
        private demo.data.A a;
        
        @RequestMapping("/abc")
        @ResponseBody
        public String index(){
            specialtyMapper.getSpecialtyList("广东省");
            return a.data;
        }
        
    }
    

    读取配置文件

    读取配置文件需要使用修饰器,@PropertySource(value = "classpath:/trip/footprint/config/redis_bae.properties")。classpath后面跟着的是配置文件路径。当然入口类记得用@ComponentScan("demo.config")扫描包。加载配置文件,当然要注入变量,用修饰器@Value("${变量名}")即可注入。代码如下:

    package demo.config;
    
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    @Configuration
    @PropertySource(value="classpath:/demo/config/db_local.properties", ignoreResourceNotFound=true)
    public class MyBatisConfig {
        
        @Value("${driverClassName}")
        private String driverClassName;
        
        @Value("${url}")
        private String url;
        
        @Value("${db_username}")
        private String username;
        
        @Value("${password}")
        private String password;
        
        /**
         * 创建数据源
         * @Primary 该注解表示在同一个接口有多个实现类可以注入的时候,默认选择哪一个,而不是让@autowire注解报错 
         */
        @Bean
        //@Primary
        public DataSource getDataSource() throws Exception{
            Properties props = new Properties();
            props.put("driverClassName", this.driverClassName);
            props.put("url", this.url);
            props.put("username", this.username);
            props.put("password", this.password);
            return DruidDataSourceFactory.createDataSource(props);
        }
    
        /**
         * 根据数据源创建SqlSessionFactory
         */
        @Bean
        public SqlSessionFactory sqlSessionFactory(DataSource ds) throws Exception{
            SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
            fb.setDataSource(ds);//指定数据源(这个必须有,否则报错)
            //下边两句仅仅用于*.xml文件,如果整个持久层操作不需要使用到xml文件的话(只用注解就可以搞定),则不加
            //fb.setTypeAliasesPackage("com.xxx.firstboot.domain");//指定基包
            //fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));//指定xml文件位置
            
            return fb.getObject();
        }
        
    }
    

    配置文件如下:

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/map?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
    db_username=root
    password=root
    

    日志输出

    在src/main/resources新建一个文件,写入下面内容:

    logging.file=log/myapp.log
    logging.level.org.springframework.web=DEBUG
    logging.level.root=DEBUG
    

    代码输出日志,代码如下:

    package demo.controller;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class Debug {
        
        @Autowired
        private demo.mapper.SpecialtyMapper specialtyMapper;
        
        @Autowired
        private demo.data.A a;
        
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
        
        @RequestMapping("/abc")
        @ResponseBody
        public String index(){
            logger.debug("ceshi");
            logger.info("对的");
            specialtyMapper.getSpecialtyList("广东省");
            return a.data;
        }
        
    }
    
    

    导出成war

    其实主要是修改pom.xml,添加下面代码:

    <!-- 打包成war需要 -->
            <dependency>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-starter-tomcat</artifactId>  
                <scope>provided</scope>  
            </dependency>  
    <!-- end -->
    
    <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
                <plugin>
                  <artifactId>maven-war-plugin</artifactId>
                  <version>3.0.0</version>
                  <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
                </plugin>
            </plugins>
        </build>
    

    修改pom.xml文件的packaging标签变成<packaging>war</packaging>

    然后再用maven build一下:

    打包配置

    相关文章

      网友评论

        本文标题:从0开始编写一个spring boot 应用

        本文链接:https://www.haomeiwen.com/subject/uqznqxtx.html