美文网首页
使用idea写一个简单的Spring Web程序 —— 不使用x

使用idea写一个简单的Spring Web程序 —— 不使用x

作者: 施瓦 | 来源:发表于2018-08-27 11:10 被阅读0次

    很久没有开坑了 这次记录一下使用idea工具来搭建一个最简单但是可运行的Spring Web应用程序,这个应用程序不使用web.xml进行配置~

    MAVEN

    首先,看下maven需要用到哪些包 :

    <?xml version="1.0" encoding="UTF-8"?>
    <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>groupId</groupId>
        <artifactId>第六章 渲染视图</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.0.8.RELEASE</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>5.0.8.RELEASE</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.0.8.RELEASE</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>4.0.1</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>4.3.12.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>4.3.12.RELEASE</version>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.12</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.6</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
            <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>2.0.1.Final</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
            <dependency>
                <groupId>org.hibernate.validator</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>6.0.12.Final</version>
            </dependency>
        </dependencies>
    </project>
    

    目录结构

    然后我们通过maven的目录结构,在src/main目录下创建一个webapp包:


    image.png

    然后在webapp下再建立两个目录,resources和views。resources用来保存js、css信息,views保存页面信息……java目录下,建立以下目录 :config、controller、dao、pojo(是的,service省略了,因为重点不在业务处理,而是构建一个简单的Spring Web应用程序)。
    建了这么多的目录,看一下现在的目录结构 :


    image.png

    创建完之后,你还需要在idea中进行如下设置 :

    image.png

    add -> Web -> 删除①中idea为我们打算生成的web.xml->改变②中的web路径

    image.png

    配置DispathcerServlet

    配置DispatcherServlet需要继承Spring的类 :AbstractAnnotationConfigDispatcherServletInitializer

    package config;
    
    public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
       // 加载驱动应用后端的中间层和数据层组件
        protected Class<?>[] getRootConfigClasses() {
            return new Class[]{RootConfig.class};
        }
        // 加载Web组件的bean 如控制器、视图解析器以及处理器映射
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{WebConfig.class};
        }
       // 将DispatcherServlet映射到"/"
        protected String[] getServletMappings() {
            return new String[]{"/"};
        }
    }
    }
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(value = "controller")
    public class WebConfig implements WebMvcConfigurer {
    
        @Bean
        public ViewResolver viewResolver(){
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix("/views/");
            resolver.setSuffix(".html");
            resolver.setExposeContextBeansAsAttributes(true);
            return resolver;
        }
    
        // 配置静态资源的处理
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
        
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/resources/")
                    .addResourceLocations("/resources/**");
        }
    }
    
    @Configuration
    @ComponentScan(basePackages = {"dao"})
    public class RootConfig {
    
    }
    

    编写控制器和视图

    package controller;
    @Controller
    @RequestMapping(value = "/")
    public class HomeController {
        @GetMapping
        public String home(){
            return "home";
        }
    }
    

    视图存放在下面的位置 :


    image.png

    我使用了semantic-ui来美化界面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>微博</title>
        <!--jquery-->
        <script src="/resources/static/base/jquery.min.js" type="text/javascript"></script>
        <!--semantic ui-->
        <link href="/resources/static/base/font.css" type="text/css" rel="stylesheet"/>
        <script src="/resources/static/semantic/semantic.min.js" type="text/javascript"></script>
        <link href="/resources/static/semantic/semantic.min.css" type="text/css" rel="stylesheet"/>
    
    </head>
    
    <body>
    <div class="ui text container">
        <div class="ui two column centered grid" style="padding-top: 5%;">
            <div class="center aligned column">
                <h1>欢迎来到Spittr</h1>
            </div>
            <div class="column row">
                <div class="center aligned column">
                    <a href="/spittles">Spittles</a>
                    ||
                    <a href="/spitter/register">注册</a>
                </div>
    
            </div>
        </div>
    </div>
    
    </body>
    
    </html>
    

    运行

    image.png
    image.png
    image.png
    image.png
    image.png

    运行效果如图所示 :


    image.png

    数据库连接

    现在,运行效果图出现在了上面,我们要为这个程序加上数据库方面的配置 :
    首先,需要在数据库中创建表

    CREATE TABLE `spittle` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `message` varchar(100) NOT NULL,
      `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      `latitude` double DEFAULT NULL,
      `longitude` double DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8
    

    然后,为这张表加几个数据 :

    INSERT INTO graduate.spittle (message,created_at,latitude,longitude) VALUES 
    ('hello world','2018-08-23 22:27:02.000',NULL,NULL)
    ,('第二条推特','2018-08-23 22:30:51.000',NULL,NULL)
    ,('天气不错','2018-08-23 22:37:40.000',NULL,NULL)
    ,('吃饭了吗','2018-08-24 05:17:17.000',NULL,NULL)
    ,('老古董怎么样','2018-08-24 05:17:42.000',NULL,NULL)
    ,('老许发表全新专辑','2018-08-24 05:17:59.000',NULL,NULL)
    ,('大千世界观后感','2018-08-24 05:18:15.000',NULL,NULL)
    ,('风居住的街道','2018-08-24 05:18:15.000',NULL,NULL)
    ,('寻宝游戏','2018-08-24 05:18:15.000',NULL,NULL)
    ,('动物世界','2018-08-24 05:18:15.000',NULL,NULL)
    ;
    INSERT INTO graduate.spittle (message,created_at,latitude,longitude) VALUES 
    ('燕归巢','2018-08-24 05:18:15.000',NULL,NULL)
    ,('艺术家们','2018-08-24 05:18:15.000',NULL,NULL)
    ,('九月清晨','2018-08-24 05:18:15.000',NULL,NULL)
    ,('重复重复','2018-08-24 05:33:05.000',NULL,NULL)
    ,('明智之举','2018-08-24 05:33:05.000',NULL,NULL)
    ,('柳成荫','2018-08-24 05:33:05.000',NULL,NULL)
    ;
    

    配置数据源

    我们在config包下面新建DataConfig类来配置数据源

    package config;
    @Configuration
    public class DataConfig {
        @Bean
        public DataSource dataSource() throws SQLException {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDbType("mysql");
            dataSource.setUrl("jdbc:mysql://127.0.0.1/graduate?serverTimezone=GMT&useSSL=false");
            dataSource.setUsername("root");
            dataSource.setPassword("root");
            // 配置WallFilter
            dataSource.setFilters("wall");
            // PsCache
            dataSource.setPoolPreparedStatements(false);
            return dataSource;
        }
        @Bean
        public JdbcOperations jdbcOperations(DataSource dataSource){
            return new JdbcTemplate( dataSource);
        }
    }
    

    当然,你还可以把数据库连接参数信息放到配置文件中 :

    @Configuration
    @PropertySource(value = "classpath:/application.properties")
    public class DataConfig {
    
        private final Environment environment;
    
        @Autowired
        public DataConfig(Environment environment) {
            this.environment = environment;
        }
    
        @Bean
        public DataSource dataSource() throws SQLException {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDbType(environment.getProperty("datasource.dbtype"));
            dataSource.setUrl(environment.getProperty("datasource.url"));
            dataSource.setUsername(environment.getProperty("datasource.username"));
            dataSource.setPassword(environment.getProperty("datasource.password"));
            // 配置WallFilter
            dataSource.setFilters("wall");
            // PsCache
            dataSource.setPoolPreparedStatements(false);
            return dataSource;
        }
        @Bean
        public JdbcOperations jdbcOperations(DataSource dataSource){
            return new JdbcTemplate( dataSource);
        }
    }
    

    之后,我们修改RootConfig类:

    @Configuration
    @Import(value = {DataConfig.class})
    @ComponentScan(basePackages = {"dao"})
    public class RootConfig {
    
    }
    

    POJO

    public class Spittle {
    
        private final Long id;
        private final String message;
        private final Timestamp time;
        private Double latitude;
        private Double longitude;
        // 省略set和get方法
    }
    

    编写dao层

    package dao;
    
    import pojo.Spittle;
    
    import java.util.List;
    
    public interface SpittleRepository {
        /**
         *
         * @param max Spittle中ID的最大个数
         * @param count 最多返回的Spittle个数
         * @return
         */
        List<Spittle> findSpittles(long max,int count);
        Spittle findSpittle(Long spittleId);
    }
    
    
    @Repository
    public class JdbcSpittleRepository implements SpittleRepository {
        private final JdbcOperations jdbcOperations;
        @Autowired
        public JdbcSpittleRepository(JdbcOperations jdbcOperations) {
            this.jdbcOperations = jdbcOperations;
        }
        @Override
        public List<Spittle> findSpittles(long max , int count) {
            return jdbcOperations.query("SELECT * FROM spittle WHERE ID < ? ORDER BY created_at desc LIMIT ?" ,
                    new SpittleRowMapper() , max , count);
        }
    
        @Override
        public Spittle findSpittle(Long spittleId) {
            return jdbcOperations.queryForObject("SELECT * FROM spittle WHERE id = ?",
                    new SpittleRowMapper(),spittleId);
        }
        private class SpittleRowMapper implements RowMapper<Spittle>{
            @Override
            public Spittle mapRow(ResultSet resultSet , int i) throws SQLException {
                return new Spittle(resultSet.getLong("id"),
                        resultSet.getString("message"),
                        resultSet.getTimestamp("created_at"),
                        resultSet.getDouble("latitude"),
                        resultSet.getDouble("longitude")
                );
            }
        }
    }
    

    编写controller层

    @Controller
    @RequestMapping(value = "/spittles")
    public class SpittleController {
    
        private final JdbcSpittleRepository spittleRepository;
        private final String MAX_LONG_AS_STRING = "2147483647";
    
        @Autowired
        public SpittleController(JdbcSpittleRepository spittleRepository) {
            this.spittleRepository = spittleRepository;
        }
    
        @GetMapping
        public String showSpittle(){
            return "/spittles";
        }
    
        @PostMapping
        @ResponseBody
        public Object spittleList(
                @RequestParam(value = "max" , defaultValue = MAX_LONG_AS_STRING) long max,
                @RequestParam(value = "count" , defaultValue = "10") int count){
            return spittleRepository.findSpittles(max,count);
        }
    }
    

    spittles.html

    <!DOCTYPE html>
    <head>
        <meta charset="UTF-8">
        <title>当前列表</title>
    
        <!--jquery-->
        <script src="/resources/static/base/jquery.min.js" type="text/javascript"></script>
        <!--ajax-->
        <script src="/resources/static/base/axios.min.js"></script>
        <!--semantic ui-->
        <link href="/resources/static/base/font.css" type="text/css" rel="stylesheet"/>
        <script src="/resources/static/semantic/semantic.min.js" type="text/javascript"></script>
        <link href="/resources/static/semantic/semantic.min.css" type="text/css" rel="stylesheet"/>
        <!--vue-->
        <script src="/resources/static/vue/vue.js"></script>
        <!--日期格式化-->
        <script src="/resources/static/moment/moment.js"></script>
        <!--本页面的js-->
        <script src="/resources/static/views/spittles.js"></script>
    </head>
    <body>
        <div class="ui text container">
            <div class="ui grid" style="padding-top: 5%">
                <div class="row">
                    <div class="ui ordered list" id="spittlesList">
                        <div class="item" v-for="spittle in spittles">
                            <a v-bind:href="'/spittles/show/'+ spittle.id">{{ spittle.message }}</a>
                            <div class="description">
                                {{ spittle.time | formateDate }}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </body>
    </html>
    

    spittles.js

    var spittlesList;
    
    $(function () {
        axios.post('/spittles', {
    
        }).then(function (response) {
            spittlesList = new Vue({
                el : '#spittlesList',
                data : {
                    spittles : response.data
                },
                filters : {
                    formateDate: function (value) {
                        moment.locale("zh_cn");
                        return moment(value).format("lll");
                    }
                }
            });
        }).catch(function (error) {
            console.log(error);
        });
    
    });
    

    页面显示如下图所示 :


    image.png

    虽然很多事情我们还没有处理,比方说异常的处理,比方说其他事件的处理……但是,这就不是这个页面所要表达的重点了。

    相关文章

      网友评论

          本文标题:使用idea写一个简单的Spring Web程序 —— 不使用x

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