Spring MVC绑定 List 对象参数 原

       最近做的一个小小的项目碰上了如何用 post 传递一整个 list 的问题,在解决这个问题的同时,也顺带升级一下 Spring 的版本,并精简一下代码,不过对新的用法没有时间去做太多的探索。

       最近也在看 Spring Boot,但是部分配置还没来理解,暂时还没办法用到工程里面来。不多说,一点一点挤牙膏吧。

项目已放到 Github:https://github.com/gaussic/SpringDemo-List

转载请注明出处:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 。

一、开发环境

IntelliJ IDEA 2016.1.2

JDK 1.8.0_92

Tomcat 8.0.35

Maven 3.0.5

Spring 4.2.6.RELEASE

Hibernate 5.1.0.Final

Spring Data JPA 1.10.1.RELEASE

二、配置项目

具体的创建步骤不多说了。

贴出 pom.xml:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.gaussic</groupId>
    <artifactId>springdemo-list</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>springdemo-list Maven Webapp</name>
    <url>http://maven.apache.org</url>

    <properties>
        <spring.version>4.2.6.RELEASE</spring.version>
        <hibernate.version>5.1.0.Final</hibernate.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.10.1.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.39</version>
        </dependency>


    </dependencies>
    <build>
        <finalName>springdemo-list</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <display-name>SpringDemo-List Web Application</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

</web-app>

先把 package 建立好:

配置 mvc-dispatcher-servlet.xml,注意这里把数据库的配置也同样放了进来,所以就不需要 persistence.xml 了:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:component-scan base-package="com.gaussic.controller"/>

    <mvc:default-servlet-handler/>

    <mvc:annotation-driven/>

    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 表示JPA Repository所在的包 -->
    <jpa:repositories base-package="com.gaussic.repository"/>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="defaultPersistenceUnit"/>
        <property name="packagesToScan" value="com.gaussic.model"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
                <prop key="hibernate.connection.url">jdbc:mysql://localhost:3306/springdemo-list?useSSL=false</prop>
                <prop key="hibernate.connection.username">root</prop>
                <prop key="hibernate.connection.password">111111</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.connection.useUnicode">true</prop>
                <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.use_sql_comments">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.connection.autoReconnect">true</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="connection.autoReconnectForPools">true</prop>
                <prop key="connection.is-connection-validation-required">true</prop>
            </props>
        </property>
    </bean>

    <!-- 事务管理 -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <!-- 开启事务管理注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

三、数据库配置

创建数据库 springdemo-list,utf-8 格式,演示比较简单,只有一张表(主键 id 一定要设置为自增):

构造 UserEntity。

这一步有一点小 trick。因为直接在mvc-dispatcher-servlet.xml里面配置数据库,没有添加 Java EE Persistence 这个 Framework,所以在左下的 Toolbar 无法看到 Persistence 这个选项。怎么做才能把它给调出来呢?

简单的做法是右击项目,添加 Framework:

下拉找到 Java EE Persistence,直接 OK,其他不用配置。

可以发现,resources里面多了 persistence.xml,而左下角多了 Persistence:

这个时候就可以正常地生成 Entity 了:

在 com.gaussic.model 中生成了 UserEntity:

package com.gaussic.model;

import javax.persistence.*;

/**
 * Created by dzkan on 2016/5/24.
 */
@Entity
@Table(name = "user", schema = "springdemo-list", catalog = "")
public class UserEntity {
    private int id;
    private String firstName;
    private String lastName;

    @Id
    @Column(name = "id", nullable = false)
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Basic
    @Column(name = "first_name", nullable = true, length = 45)
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @Basic
    @Column(name = "last_name", nullable = true, length = 45)
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        UserEntity that = (UserEntity) o;

        if (id != that.id) return false;
        if (firstName != null ? !firstName.equals(that.firstName) : that.firstName != null) return false;
        if (lastName != null ? !lastName.equals(that.lastName) : that.lastName != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
        result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
        return result;
    }
}

既然 entity 已经生成了,Persistence 就功德圆满了,可以删掉 resources 下的 persistence.xml 了。

四、添加 Repository

刚配置完数据库,现在要配 Repository 了。稍微提一下,JPA 是一种规范,基于这种规范可以非常方便地进行数据库操作,而 Hibernate JPA 实现了这一规范,这也是我们为什么要导入 Hibernate JPA 的原因,导入归导入,但使用的还是 Spring Data JPA 的语法。

新建 UserRepository:

package com.gaussic.repository;

import com.gaussic.model.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * Created by dzkan on 2016/5/24.
 */
public interface UserRepository extends JpaRepository<UserEntity, Integer> {

    // 由于后面要实现一个简单的查重,需要这个方法,查询指定姓和名的人的个数
    Long countByFirstNameAndLastName(String firstName, String lastName);
}

五、添加 Controller

1、首页

我们想在首页先试一下数据库中有多少个用户。

新建 DemoController:

package com.gaussic.controller;

import com.gaussic.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * Created by dzkan on 2016/5/24.
 */
@Controller
public class DemoController {

    @Autowired
    UserRepository userRepository;

    // 首页
    @RequestMapping("/")
    public String index(ModelMap model) {
        model.addAttribute("user_cnt", userRepository.count());
        return "index";
    }
}

在 WEB-INF 下新建 pages 文件夹,把 index.jsp 拖到这个文件夹下:

修改 index.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>用户导入系统首页</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>

<div class="container">
    <h3>用户导入系统首页</h3>
    <hr style="border-color: steelblue"/>
    <h4>数据库中已有 <span style="color: red">${user_cnt}</span> 名用户 。</h4>
    <br/>
    <br/>
    <a href="${pageContext.request.contextPath}/users" type="button" class="btn btn-success">进入用户系统</a>
</div>

<script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</body>
</html>

配置 Tomcat,部署并运行(不再赘述):

2、批量输入数据

接下来就要完成我的下一个目标,如何批量的输入数据,即一次性输入多个用户。

首先,要找个方法把多个用户用列表封装起来。在 com.gaussic.model 下新建一个 UserListForm,这个类非常简单,只有一个 list 及其 get 和 set 方法:

package com.gaussic.model;

import java.util.List;

/**
 * Created by dzkan on 2016/5/24.
 */
public class UserListForm {

    private List<UserEntity> users;

    public List<UserEntity> getUsers() {
        return users;
    }

    public void setUsers(List<UserEntity> users) {
        this.users = users;
    }
}

在 DemoController 中添加方法,映射到批量添加用户页面:

    // 指向批量添加用户页面
    @RequestMapping("/users")
    public String users() {
        return "users";
    }

在 pages 下新建页面 users.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>用户输入</title>

    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>

<div class="container">
    <h3>请输入用户姓名</h3>
    <hr style="border-color: steelblue"/>

    <form class="form-horizontal" action="${pageContext.request.contextPath}/addUser" method="post">
        <div class="question-list panel panel-success" style="padding:10px; font-size: 16px;">
            <c:forEach var="i" begin="1" end="3">
                <div class="form-group">
                    <label for="firstName${i}" class="col-md-2 control-label">First Name ${i}:</label>
                    <div class="col-md-10">
                        <input type="text" class="form-control" id="firstName${i}" name="users[${i-1}].firstName"
                               required="required">
                    </div>
                </div>
                <div class="form-group">
                    <label for="lastName${i}" class="col-md-2 control-label">Last Name ${i}:</label>
                    <div class="col-md-10">
                        <input type="text" class="form-control required" id="lastName${i}" name="users[${i-1}].lastName"
                               required="required">
                    </div>
                </div>
            </c:forEach>
        </div>

        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="button" class="btn btn-info" id="addBtn">
                    <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                </button>
            </div>
        </div>
        
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" class="btn btn-success">提交</button>
            </div>
        </div>
    </form>
</div>

<script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>
    $("#addBtn").click(function () {
        var user_num = $(".question-list .form-group").length / 2;
        if (user_num < 5) {
            var firstName = "<div class=\"form-group\">"
                    + "<label for=\"firstName" + (user_num + 1) + "\" class=\"col-md-2 control-label\">First Name " + (user_num + 1) + ":</label>"
                    + "<div class=\"col-md-10\">"
                    + "<input type=\"text\" class=\"form-control\" id=\"firstName" + (user_num + 1) + "\" name=\"users[" + (user_num) + "].firstName\" required=\"required\">"
                    + "</div></div>";

            var lastName = "<div class=\"form-group\">"
                    + "<label for=\"lastName" + (user_num + 1) + "\" class=\"col-md-2 control-label\">Last Name " + (user_num + 1) + ":</label>"
                    + "<div class=\"col-md-10\">"
                    + "<input type=\"text\" class=\"form-control\" id=\"lastName" + (user_num + 1) + "\" name=\"users[" + (user_num) + "].lastName\" required=\"required\">"
                    + "</div></div>";

            $(".question-list").append(firstName + lastName);
        } else {
            alert("最多只能输入 5 个用户,若想输入更多,请在提交本页后重新进入。");
        }
    });
</script>
</body>
</html>

注意以下几点,其中 name 中的参数要严格按照 UserListForm 的参数名:

看看效果:

这里多了一个挺好玩的小功能,就是在数量不够的手动添加。页面已经做好了,现在要实现它的 post 方法了:

在 DemoController 中添加如下方法:

    // 添加用户,post 请求
    @RequestMapping(value = "/addUser", method = RequestMethod.POST)
    public String addUser(UserListForm userListForm, ModelMap model) {

        List<UserEntity> succeedList = new ArrayList<>();  // 添加成功
        List<UserEntity> failList = new ArrayList<>();     // 添加不成功
        for(UserEntity user : userListForm.getUsers()) {
            // 基本查重
            if(userRepository.countByFirstNameAndLastName(user.getFirstName(), user.getLastName()) == 0) {
                userRepository.saveAndFlush(user);
                succeedList.add(user);
            } else {
                failList.add(user);
            }
        }
        
        model.addAttribute("succeedList", succeedList);
        model.addAttribute("failList", failList);
        return "user_list";
    }

然后,创建一个页面,返插入结果:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <title>用户输入结果</title>

    <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/custome.css">

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>
<body>

<div class="container">
    <h3>用户输入结果列表</h3>
    <hr style="border-color: steelblue"/>

    <div class="question-list panel panel-success" style="padding:10px;">
        <h3>以下是输入成功的用户,数量 <span style="color: red">${succeedList.size()}</span></h3>
        <c:forEach var="i" begin="1" end="${succeedList.size()}">
            <h4 style="padding: 5px;">First Name ${i}: ${succeedList[i-1].firstName}</h4>
            <h4 style="padding: 5px;">Last Name ${i}: ${succeedList[i-1].lastName}</h4>
        </c:forEach>
    </div>

    <div class="question-list panel panel-success" style="padding:10px;">
        <h3>以下用户库中已存在,数量 <span style="color: red">${failList.size()}</span></h3>
        <c:forEach var="i" begin="1" end="${failList.size()}">
            <h4 style="padding: 5px;">First Name ${i}: ${failList[i-1].firstName}</h4>
            <h4 style="padding: 5px;">Last Name ${i}: ${failList[i-1].lastName}</h4>
        </c:forEach>
    </div>

    <div class="row" style="margin-bottom: 50px;">
        <div class="col-sm-offset-5 col-sm-7">
            <a type="button" href="${pageContext.request.contextPath}/users" class="btn btn-info"
               style="font-weight: bold; margin-bottom: 5px;">继续输入</a>
            <a type="button" href="${pageContext.request.contextPath}/" class="btn btn-info"
            style="font-weight: bold; margin-bottom: 5px;">返回首页</a>
        </div>
    </div>
</div>

<script src="http://cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</body>
</html>

看看效果:

任务完成,其他的任务就不加进来了。按道理说,这个项目稍微改改就可以自己用了,可以省去不少配置的时间。

项目已放到 Github:https://github.com/gaussic/SpringDemo-List

转载请注明出处:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

linux 内核同步机制使用

Linux 内核中的同步机制:原子操作、信号量、读写信号量、自旋锁的API、大内核锁、读写锁、大读者锁、RCU和顺序锁。 1、介绍 在现代操作系统里,同一时间...

3325
来自专栏IT可乐

Junit 入门使用教程

1、Junit 是什么?   JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的s...

2285
来自专栏爱撒谎的男孩

Springmvc响应Ajax请求(@ResponseBody)

2K8
来自专栏JackieZheng

学习SpringMVC——说说视图解析器

  各位前排的,后排的,都不要走,咱趁热打铁,就这一股劲我们今天来说说spring mvc的视图解析器(不要抢,都有位子~~~)   相信大家在昨天那篇如何获取...

25110
来自专栏程序猿DD

Spring Boot使用@Async实现异步调用:自定义线程池

在之前的Spring Boot基础教程系列中,已经通过《Spring Boot中使用@Async实现异步调用》一文介绍过如何使用 @Async注解来实现异步调用...

5758
来自专栏Golang语言社区

Golang同步:锁的使用案例详解

互斥锁 互斥锁是传统的并发程序对共享资源进行访问控制的主要手段。它由标准库代码包sync中的Mutex结构体类型代表。只有两个公开方法 Lock Unlock ...

3828
来自专栏Android相关

Gradle For Android(7)--创建Task以及Plugin

到目前为止,我们已经看到了很多Gradle构建的属性,并且知道了怎么去执行Tasks。这一章,会更多的了解这些属性,并且创建我们自己的Task。一旦知道如何自定...

1322
来自专栏你不就像风一样

[转]Spring基础知识汇总 Java开发必看

Spring框架由Rod Johnson开发,2004年发布了Spring框架的第一版。Spring是一个从实际开发中抽取出来的框架,因此它完成了大量开发中的通...

1293
来自专栏JMCui

再学习之Spring(依赖注入).

一、概述     Spring框架是以 简化Java EE应用程序的开发 为目标而创建的。Spring可以实现很多功能,但是这些功能的底层都依赖于它的两个核心特...

3696
来自专栏前端说吧

JS-时间处理函数封装汇总 (更新中...)

最近听说thymeleaf好像也挺流行的,还说是spring官方推荐使用,那thymeleaf究竟是什么呢?spring为什么推荐用它呢?怎么用呢?本文将为你揭...

843

扫码关注云+社区