使用idea寫一個簡單的Spring Web程序 —— 不使用xml配置

很久沒有開坑了 這次記錄一下使用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目錄下創(chuàng)建一個webapp包:


image.png

然后在webapp下再建立兩個目錄,resources和views。resources用來保存js、css信息,views保存頁面信息……java目錄下,建立以下目錄 :config、controller、dao、pojo(是的,service省略了,因為重點不在業(yè)務處理,而是構建一個簡單的Spring Web應用程序)。
建了這么多的目錄,看一下現(xiàn)在的目錄結構 :


image.png

創(chuàng)建完之后,你還需要在idea中進行如下設置 :

image.png

add -> Web -> 刪除①中idea為我們打算生成的web.xml->改變②中的web路徑

image.png

配置DispathcerServlet

配置DispatcherServlet需要繼承Spring的類 :AbstractAnnotationConfigDispatcherServletInitializer

package config;

public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
   // 加載驅動應用后端的中間層和數(shù)據(jù)層組件
    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;
    }

    // 配置靜態(tài)資源的處理
    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

數(shù)據(jù)庫連接

現(xiàn)在,運行效果圖出現(xiàn)在了上面,我們要為這個程序加上數(shù)據(jù)庫方面的配置 :
首先,需要在數(shù)據(jù)庫中創(chuàng)建表

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

然后,為這張表加幾個數(shù)據(jù) :

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)
,('老許發(fā)表全新專輯','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)
;

配置數(shù)據(jù)源

我們在config包下面新建DataConfig類來配置數(shù)據(jù)源

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);
    }
}

當然,你還可以把數(shù)據(jù)庫連接參數(shù)信息放到配置文件中 :

@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的最大個數(shù)
     * @param count 最多返回的Spittle個數(shù)
     * @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

雖然很多事情我們還沒有處理,比方說異常的處理,比方說其他事件的處理……但是,這就不是這個頁面所要表達的重點了。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容