Thymeleaf MVC 集成Spring

源码下载链接:

https://github.com/thymeleaf/thymeleafexamples-gtvg

https://github.com/thymeleaf/thymeleafexamples-stsm


本篇博客主要是在上述两个工程的基础上,仿照stsm工程为gtvg集成Spring框架,使其@Controller等元数据,通过对

Thymeleaf +Spring官方文档的解读,参照Spring Expression Language (SpEL)语言规则对gtvg进行适当的修改。


实验工具:Eclipse, Chrome 浏览器


本次实验主要是在gtvg的基础上进行修改,其项目的基本结构保持不变。

第一步:Maven工程首先应该配置pom.xml,添加需要的依赖

主要的修改为: artifactId 修改为 my_mvn, 添加Spring框架版本及相应的Spring依赖。


<?xml version="1.0" encoding="UTF-8"?>

<!-- ========================================================================= -->
<!--                                                                           -->
<!--   Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org)  -->
<!--                                                                           -->
<!--   Licensed under the Apache License, Version 2.0 (the "License");         -->
<!--   you may not use this file except in compliance with the License.        -->
<!--   You may obtain a copy of the License at                                 -->
<!--                                                                           -->
<!--       http://www.apache.org/licenses/LICENSE-2.0                          -->
<!--                                                                           -->
<!--   Unless required by applicable law or agreed to in writing, software     -->
<!--   distributed under the License is distributed on an "AS IS" BASIS,       -->
<!--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or         -->
<!--   implied. See the License for the specific language governing            -->
<!--   permissions and limitations under the License.                          -->
<!--                                                                           -->
<!-- ========================================================================= -->

<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>thymeleafexamples</groupId>
  <artifactId>my_mvn</artifactId>
  <packaging>war</packaging>
  <version>ci</version>
  <name>Thymeleaf Examples - My Sring Thymeleaf MVC </name>

  <description>XML/XHTML/HTML5 template engine for Java</description>

  <licenses>
    <license>
      <name>The Apache Software License, Version 2.0</name>
      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
      <distribution>repo</distribution>
    </license>
  </licenses>

  <organization>
    <name>The THYMELEAF team</name>
    <url>http://www.thymeleaf.org</url>
  </organization>
  
  <scm>
    <url>scm:git:git@github.com:thymeleaf/thymeleafexamples-stsm.git</url>
    <connection>scm:git:git@github.com:thymeleaf/thymeleafexamples-stsm.git</connection>
    <developerConnection>scm:git:git@github.com:thymeleaf/thymeleafexamples-stsmgit</developerConnection>
  </scm>
  
  <developers>
    <developer>
      <id>dfernandez</id>
      <name>Daniel Fernandez</name>
      <email>daniel.fernandez AT 11thlabs DOT org</email>
      <roles>
        <role>Project admin</role>
      </roles>
     </developer>
  </developers>
  

  <repositories>
    <repository>
      <id>sonatype-nexus-snapshots</id>
      <name>Sonatype Nexus Snapshots</name>
      <url>https://oss.sonatype.org/content/repositories/snapshots</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>jboss</id>
      <url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
  </repositories>


  <properties>
    <project.build.sourceEncoding>ISO-8859-1</project.build.sourceEncoding>
    <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
    <springframework.version>4.3.3.RELEASE</springframework.version>
  </properties>
  

  <build>
  
    <resources>
    
      <resource>
        <directory>src/main/resources</directory>
      </resource>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
          <include>**/*.html</include>
        </includes>
      </resource>
      
    </resources>
        
    <plugins>
    
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.5.1</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.7</version>
        <configuration>
          <encoding>ISO-8859-1</encoding>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.2</version>
      </plugin>

    </plugins>
        
  </build>

  <profiles>
    
    <profile>
      <id>build-dist</id>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
              <execution>
                <id>make-assembly-dist</id>
                <phase>package</phase>
                <goals>
                  <goal>attached</goal>
                </goals>
                <configuration>
                  <descriptors>
                    <descriptor>${basedir}/src/assembly/sources.xml</descriptor>
                  </descriptors>
                  <appendAssemblyId>true</appendAssemblyId>
                  <finalName>${project.groupId}-${project.artifactId}-${project.version}</finalName>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
      
  </profiles>


  <dependencies>
        
        
    <dependency>
      <groupId>org.thymeleaf</groupId>
      <artifactId>thymeleaf-spring4</artifactId>
      <version>${thymeleaf.version}</version>
      <scope>compile</scope>
    </dependency>
    
        
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
        
        
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-expression</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${springframework.version}</version>
      <scope>compile</scope>
    </dependency>

        
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.0.0.GA</version>
      <scope>compile</scope>
    </dependency>
        
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator-annotation-processor</artifactId>
      <version>4.1.0.Final</version>
    </dependency>        


    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.1</version>
      <scope>compile</scope>
    </dependency>
        
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.1</version>
      <scope>compile</scope>
    </dependency>

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.15</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>
          <groupId>com.sun.jdmk</groupId>
          <artifactId>jmxtools</artifactId>
        </exclusion>
        <exclusion>
          <groupId>com.sun.jmx</groupId>
          <artifactId>jmxri</artifactId>
        </exclusion>
        <exclusion>
          <groupId>javax.jms</groupId>
          <artifactId>jms</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
        
  </dependencies>
  
</project>

第二步:删除原有的application包,仿照stms的application包对gtvg的Spring进行配置,如图所示


SpringServletInitializer.java不必修改,只需修改SpringWebConfig.java(对于该文件,我们也可以以beans.xml的形式实现),删除原有的addFormatters、varietyFormatter、dateFormatter等方法,因为我们在gtvg中并不需要stsm的VarietyFormatter等类,同时修改viewResolver方法,添加 viewResolver.setCharacterEncoding("UTF-8"),使其编码方式为 “UTF-8”,否则中文会乱码。由于我们已经有了SpringWebConfig.java 来实现配置,那么就可以删掉web.xml文件,filter包也用不到,删掉。

/*
 * =============================================================================
 *
 *   Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org)
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 * =============================================================================
 */
package thymeleafexamples.gtvg.application;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
/*import thymeleafexamples.stsm.web.conversion.DateFormatter;
import thymeleafexamples.stsm.web.conversion.VarietyFormatter;*/

@Configuration
@EnableWebMvc
@ComponentScan("thymeleafexamples.gtvg")
public class SpringWebConfig
        extends WebMvcConfigurerAdapter implements ApplicationContextAware {

    private ApplicationContext applicationContext;


    public SpringWebConfig() {
        super();
    }


    public void setApplicationContext(final ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }



    /* ******************************************************************* */
    /*  GENERAL CONFIGURATION ARTIFACTS                                    */
    /*  Static Resources, i18n Messages, Formatters (Conversion Service)   */
    /* ******************************************************************* */

    /**
     *  Dispatcher configuration for serving static resources
     */
    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        super.addResourceHandlers(registry);
        registry.addResourceHandler("/images/**").addResourceLocations("/images/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
    }

    /**
     *  Message externalization/internationalization
     */
    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("Messages");
        return messageSource;
    }

    /* **************************************************************** */
    /*  THYMELEAF-SPECIFIC ARTIFACTS                                    */
    /*  TemplateResolver <- TemplateEngine <- ViewResolver              */
    /* **************************************************************** */

    @Bean
    public SpringResourceTemplateResolver templateResolver(){
        // SpringResourceTemplateResolver automatically integrates with Spring's own
        // resource resolution infrastructure, which is highly recommended.
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.applicationContext);
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        // HTML is the default value, added here for the sake of clarity.
        templateResolver.setTemplateMode(TemplateMode.HTML);
        
        // Template cache is true by default. Set to false if you want
        // templates to be automatically updated when modified.
        templateResolver.setCacheable(true);
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine(){
        // SpringTemplateEngine automatically applies SpringStandardDialect and
        // enables Spring's own MessageSource message resolution mechanisms.
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        // Enabling the SpringEL compiler with Spring 4.2.4 or newer can
        // speed up execution in most scenarios, but might be incompatible
        // with specific cases when expressions in one template are reused
        // across different data types, so this flag is "false" by default
        // for safer backwards compatibility.
        templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }

    @Bean
    public ThymeleafViewResolver viewResolver(){
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        //
        viewResolver.setCharacterEncoding("UTF-8");
        return viewResolver;
    }

}

第三步: 修改控制器

因为我们使用@Controller、@RequestMapping等元数据,可以删除gtvg原有controller包下的所有控制器,进行重写,我下面实现了3个控制器,如图所示:



(一)对于GTVGController.java,主要实现基本的地址请求,实现如下:

GTVGController.java

package thymeleafexamples.gtvg.web.controller;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import thymeleafexamples.gtvg.business.entities.User;
import thymeleafexamples.gtvg.business.entities.Order;
import thymeleafexamples.gtvg.business.entities.Product;
import thymeleafexamples.gtvg.business.services.OrderService;
import thymeleafexamples.gtvg.business.services.ProductService;


@Controller
public class GTVGController {
	
	@Autowired
	private ProductService productService;
	
	@Autowired
	private OrderService orderService;
	
	public GTVGController() {
		// TODO Auto-generated constructor stub
		super();
	}
	
	@ModelAttribute("today")
	public Date getToday() {
		return Calendar.getInstance().getTime();
	}
	
	@ModelAttribute("prods") 
	public List<Product> showALlProducts() {
		return this.productService.findAll();
	}
	
	@ModelAttribute("orders")
	public List<Order> showAllOrders() {
		return this.orderService.findAll();
	}
	
	@RequestMapping({"/", "/gtvg"})
	public String showHome(HttpSession session) {
		session.setAttribute("user", new User("John", "Apricot", "Antarctica", null));
		return "home";
	}
	
	@RequestMapping("/userprofile")
	public String showUserProfile() {
		return "userprofile";
	}
	
	@RequestMapping("/subscribe")
	public String showSubscribe() {
		return "subscribe";
	}
	
	@RequestMapping("/product/list") 
	public String showProductList() {
		return "/product/list";
	}
	
	@RequestMapping("/order/list") 
	public String showOrderList() {
		return "/order/list";
	}
	
}


为了实现orderProduce、productService的自动装配(@Autowired),需要做一些修改,

1)对于 repositories下的所有_Repository.java文件的类名上方添加@Repository注解,


2)同理,对services包下的所有_Service.java文件,在类名的上方添加@Service注解,再添加一个_Repository类型自动装配的私有成员,

以OrderService.java为例,另外两个Service类同理,修改后的代码如下:

/*
 * =============================================================================
 * 
 *   Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org)
 * 
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * 
 * =============================================================================
 */
package thymeleafexamples.gtvg.business.services;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import thymeleafexamples.gtvg.business.entities.Order;
import thymeleafexamples.gtvg.business.entities.repositories.OrderRepository;

@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;
    
    public OrderService() {
        super();
    }
    
    
    
    public List<Order> findAll() {
        return this.orderRepository.findAll();
    }

    public Order findById(final Integer id) {
        return this.orderRepository.findById(id);
    }

    public List<Order> findByCustomerId(final Integer customerId) {
        return this.orderRepository.findByCustomerId(customerId);
    }
    
}
上述工作也相当于beans.xml的配置(注入依赖)过程


(二)另外两个控制器,主要用于处理order/details 和 product/comments 等更加细节的请求,具体实现如下:

ProductCommentsController.java

package thymeleafexamples.gtvg.web.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import thymeleafexamples.gtvg.business.entities.Product;
import thymeleafexamples.gtvg.business.services.ProductService;

@Controller
public class ProductCommentsController {
	
	@Autowired
	private ProductService productService;
	
	@ModelAttribute("prod") 
	public Product getProduct(Integer prodId) {
		return this.productService.findById(prodId);
	}
	
	@RequestMapping(path = "/product/comments", params = {"prodId"})
	public String showProductComments(final HttpServletRequest request) {
		Integer prodId = Integer.valueOf(request.getParameter("prodId"));
		getProduct(prodId);
		
		return "/product/comments";
	}
}

OrderDetailsController.java

package thymeleafexamples.gtvg.web.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import thymeleafexamples.gtvg.business.entities.Order;
import thymeleafexamples.gtvg.business.services.OrderService;

@Controller
public class OrderDetailsController {
	
	@Autowired
	private OrderService orderService;
	
	@ModelAttribute("order")
	public Order getOrder(Integer orderId) {
		return this.orderService.findById(orderId);
	}
	
	@RequestMapping(path="/order/details", params = {"orderId"})
	public String showOrderDetails(final HttpServletRequest request) {
		final int orderId = Integer.valueOf(request.getParameter("orderId"));
		getOrder(orderId);
		return "order/details";
	}
}


第四步:到第三步为止,大部分工作已经完成,最后就需要修改资源文件(.properties,.html)

1) .properties 文件

在SpringWebConfig.java 有一个messageSource方法,就是用于管理资源文件的(含有@Bean注解的类,均可以在beans.xml文件中配置)。


_.properties文件是用于实现文字国际化表达的:

参考stms的目录,可以发现,它的_.properties文件都是集中在Messages.properties中messageSource.setBasename("Messages");

因此,在src/main/resources 下新建Messages.properties 文件,将gtvg原有templates文件夹下的properties文件复制到对应版本的properties文件中

如下图所示,其中Messages.properties 文件包含了gtvg中home.properties、userfile.properties以及list.properties的内容


这里还有另外一种方法,就是不需要将全部的.properties文件整合到Messages文件中(但是要移到resources文件下),如果有很多文件,这会很麻烦。我们可以修改messageSource方法,如图所示,调用messageSource.addBasenames方法将我们的properties文件动态地注入到工程中。


2) .html 文件

由于使用Spring集成,在Thymeleaf 中使用的方言有些符合OGNL,但是却不符合SpEL(Spring Expression Language), 因此我们应作出相应的修改。

比如:

对于order/list.html, 应该将${#aggregates.sum(o.orderLines.{purchasePrice * amount})}修改为

    ${#aggregates.sum(o.orderLines.![purchasePrice * amount])}

对于order/details.html 也要作上述修改,还有 SpEL 在 '{th:object,data-th-object}' 只支持(${...}),

因此需要将 <div th:object="*{customer}">修改为<div th:object="{$order.customer}">



第五步:到此为止,我们完成了Spring的集成工作,可以检验一下我们的结果,clean compile tomcat7:run 运行程序,与原有gtvg的项目结果进行比对,如果完全一样,则我们正确集成了Spring。

注意:测试时根URI为localhost:8080/my_mvn/, my_mvn是我们的工程名


参考链接:

http://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html

http://www.thymeleaf.org/doc/articles/springmvcaccessdata.html

http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/expressions.html

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc

http://www.cnblogs.com/suncj/p/4028768.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值