JDK 版本 |
---|
本文的目标是采用基于Java
配置的方式搭建Spring+SpringMVC+SpringData+JPA
。本文只是简单的演示一下具体的配置,没有任何繁琐复杂的逻辑业务,目的是体验一下Spring
无XML
该如何配置。最后展示一下SpringData
提供的分页封装类Page
的效果。
项目依赖 |
---|
<properties>
<argLine>-Dfile.encoding=UTF-8</argLine>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
<spring.version>4.3.2.RELEASE</spring.version>
<spring.data.version>1.10.2.RELEASE</spring.data.version>
<hibernate5.version>5.2.2.Final</hibernate5.version>
<hibernate5.validation.version>5.2.4.Final</hibernate5.validation.version>
<hibernate4.version>4.3.11.Final</hibernate4.version>
<hibernate4.validation.version>4.3.2.Final</hibernate4.validation.version>
<jackson.version>2.8.1</jackson.version>
<project.context.path>/</project.context.path>
<project.port>80</project.port>
</properties>
<dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>javax.servlet.jsp.jstl-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- web -->
<!-- service -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- service -->
<!-- test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- test -->
<!-- log -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.logback-extensions</groupId>
<artifactId>logback-ext-spring</artifactId>
<version>0.1.4</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
</dependency>
<!-- log -->
<!-- dao -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.25</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>jconsole</artifactId>
</exclusion>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>tools</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring.data.version}</version>
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<!--<version>${hibernate4.version}</version>-->
<version>${hibernate5.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<!--<version>${hibernate4.version}</version>-->
<version>${hibernate5.version}</version>
</dependency>
<!-- dao -->
<!-- integration -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- integration -->
<!-- utility -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<!-- utility -->
</dependencies>
说明:本文所使用框架版本大多为作文时的最新版本,其中Spring
版本为4.3.2.RELEASE
,JPA
规范版本为2.1
,采用Hibernate 5.2.2.Final
作为实现,SpringData
采用1.10.2.RELEASE
版本。要求Serlvet
容器必须支持Servlet3.0
及以上,即使用tomcat
的话必须是7
以上,使用jetty
的话则必须是8
以上。
首先是Spring
的配置,主要配置数据源、entityManagerFactory
、transactionManager
等。
需要用到如下两个配置文件:
db.properties
mysql.url = jdbc:mysql:///springmvc
mysql.driverClassName = com.mysql.jdbc.Driver
mysql.username = root
mysql.password =
druid.minIdle = 1
druid.maxActive = 10
druid.testWhileIdle = false
hbm.properties
hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql = true
hibernate.format_sql = true
hibernate.hbm2ddl.auto = update
## 二级缓存
hibernate.cache.use_second_level_cache = true
hibernate.cache.region.factory_class = org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate.cache.provider_configuration_file_resource_path = classpath:cache/ehcache.xml
hibernate.cache.use_query_cache = true
# 只有使用 @javax.persistence.Cacheable 注解标注的实体能够被缓存
jpa.shared-cache-mode = ENABLE_SELECTIVE
SpringConfig
应用上下文配置类,该类通常对应着applicationContext.xml
文件
package org.junbin.spring.javaconfig.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.hibernate.cfg.Environment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.bind.annotation.ControllerAdvice;
import javax.persistence.SharedCacheMode;
import java.util.HashMap;
import java.util.Map;
/**
* @author : Chung Junbin
* @email : <a href="mailto:rekadowney@163.com">发送邮件</a>
* @createDate : 2016-09-01 10:08
* @description :
* <pre>
* 特别注意:在 Spring 主配置(称为应用上下文配置)类,千万不要基于根目录扫描整个目录,否则它会将 config 目录中的
* 其他配置类也扫描并实例化,此时使用 JUnit 测试非 Web 环境下时提示没有找到 Web 上下文,导致单元测试失败。
* 即建议/要求 {@link ComponentScan#basePackages()} 应该具体到 repository 和 service 等 Component 组件的
* 包路径,而不是包含两者的上级目录
* </pre>
*/
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = false, exposeProxy = true)
@EnableTransactionManagement(proxyTargetClass = false)
@EnableJpaRepositories(basePackages = {"org.junbin.spring.javaconfig.repository"},
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager")
@PropertySource(encoding = "UTF-8", value = {"classpath:bundle/db.properties", "classpath:bundle/hbm.properties"})
@ComponentScan(basePackages = {"org.junbin.spring.javaconfig.repository", "org.junbin.spring.javaconfig.service"}, excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, ControllerAdvice.class})
})
public class SpringConfig {
/**
* 数据源配置
*/
@Value(value = "${mysql.url}")
private String url;
@Value(value = "${mysql.driverClassName}")
private String driverClassName;
@Value(value = "${mysql.username}")
private String username;
@Value(value = "${mysql.password}")
private String password;
@Value(value = "${druid.minIdle}")
private int minIdle;
@Value(value = "${druid.maxActive}")
private int maxActive;
@Value(value = "${druid.testWhileIdle}")
private boolean testWhileIdle;
/**
* JPA 规范的 Hibernate 实现
*/
@Value(value = "${hibernate.show_sql}")
private boolean showSql;
@Value(value = "${hibernate.format_sql}")
private boolean formatSql;
@Value(value = "${hibernate.hbm2ddl.auto}")
private String hbm2ddl;
@Value(value = "${hibernate.dialect}")
private String dialect;
/**
* 二级缓存
*/
@Value(value = "${hibernate.cache.use_second_level_cache}")
private boolean useSecondLevelCache;
@Value(value = "${hibernate.cache.region.factory_class}")
private String cacheRegionFactory;
@Value(value = "${hibernate.cache.provider_configuration_file_resource_path}")
private String cacheProviderConfigLocation;
@Value(value = "${hibernate.cache.use_query_cache}")
private boolean useQueryCache;
@Value(value = "${jpa.shared-cache-mode}")
private String sharedCacheMode;
// 必须指定返回类型为 DruidDataSource 才能够执行其中的方法;如果返回 DataSource 类型是没有这两个方法的
@Bean(name = "dataSource", initMethod = "init", destroyMethod = "close")
public DruidDataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(url);
dataSource.setDriverClassName(driverClassName);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setMinIdle(minIdle);
dataSource.setMaxActive(maxActive);
dataSource.setTestWhileIdle(testWhileIdle);
return dataSource;
}
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new
LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setPackagesToScan("org.junbin.spring.javaconfig.domain", "org.junbin.spring.javaconfig.converter.jpa");
Map<String, Object> jpaPropertyMap = new HashMap<>();
jpaPropertyMap.put(Environment.DIALECT, dialect);
jpaPropertyMap.put(Environment.SHOW_SQL, showSql);
jpaPropertyMap.put(Environment.FORMAT_SQL, formatSql);
jpaPropertyMap.put(Environment.HBM2DDL_AUTO, hbm2ddl);
// 二级缓存配置
jpaPropertyMap.put(Environment.USE_SECOND_LEVEL_CACHE, useSecondLevelCache);
jpaPropertyMap.put(Environment.CACHE_REGION_FACTORY, cacheRegionFactory);
jpaPropertyMap.put(Environment.CACHE_PROVIDER_CONFIG, cacheProviderConfigLocation);
jpaPropertyMap.put(Environment.USE_QUERY_CACHE, useQueryCache);
factoryBean.setJpaPropertyMap(jpaPropertyMap);
// 设置只有使用 @javax.persistence.Cacheable 注解标注的实体能够被缓存
factoryBean.setSharedCacheMode(SharedCacheMode.valueOf(sharedCacheMode));
return factoryBean;
}
@Bean(name = "transactionManager")
public JpaTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory().getObject());
}
}
配置SpringMVC
,主要配置视图解析器以及配置静态资源映射。
SpringMVC
Web
上下文配置类,该类通常对应着serlvet-spring4mvc.xml
配置文件
package org.junbin.spring.javaconfig.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
/**
* @author : Chung Junbin
* @email : <a href="mailto:rekadowney@163.com">发送邮件</a>
* @createDate : 2016-09-01 10:09
* @description :
* <pre>
* 不使用 {@link EnableWebMvc} 注解而是直接继承于 {@link WebMvcConfigurationSupport} 或者
* {@link DelegatingWebMvcConfiguration},之后通过覆盖方法可以实现更多可选功能
* </pre>
*/
@Configuration
@ComponentScan(basePackages = {"org.junbin.spring.javaconfig.controller"}, useDefaultFilters = false,
includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {
Controller.class, ControllerAdvice.class
})})
public class SpringMvcConfig extends WebMvcConfigurationSupport {
private static final String resourceHandler = "/resources/**";
private static final String resourceLocation = "/resources/";
@Bean(name = "viewResolver")
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
viewResolver.setContentType("text/html; charset=UTF-8");
return viewResolver;
}
// 添加静态资源映射
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(resourceHandler).addResourceLocations(resourceLocation);
}
// 添加 default servlet 支持
@Override
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
接下来针对web.xml
的配置类,前面之所以要求使用支持Servlet3.0
以上的容器是因为这里我们将不使用web.xml
配置文件,全部采用基于Java
的方法来配置Servlet
、Filter
、Listener
。
这里主要要配置logback
的监听器、UTF-8
的字符编码过滤器以及OpenEntityManagerInViewFilter
。
WebXmlConfig
配置类
package org.junbin.spring.javaconfig.config;
import ch.qos.logback.ext.spring.web.LogbackConfigListener;
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.filter.CharacterEncodingFilter;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.EnumSet;
/**
* @author : Chung Junbin
* @email : <a href="mailto:rekadowney@163.com">发送邮件</a>
* @createDate : 2016-09-01 10:20
* @description :
*/
public class WebXmlConfig implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// logback 监听器
servletContext.setInitParameter("logbackConfigLocation", "classpath:logback/logback.xml");
servletContext.addListener(LogbackConfigListener.class);
// CharacterEncodingFilter 过滤器
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter("UTF-8", true);
FilterRegistration.Dynamic characterEncodingConfig = servletContext.addFilter(
"characterEncodingFilter", characterEncodingFilter
);
characterEncodingConfig.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE),// 这里限定所有客户端请求、服务器 forward、服务器 include 的请求全都需要经过 filter 处理
false, // 在所有当前已经被声明的 Filter 的前面先匹配 URL
"/*"
);
// OpenEntityManagerInViewFilter 过滤器,避免在页面上出现懒加载异常,如果我们全部使用 json 作为传输的话则可以不配置
OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
FilterRegistration.Dynamic openEntityManagerInViewConfig = servletContext.addFilter(
"openEntityManagerInViewFilter", openEntityManagerInViewFilter);
openEntityManagerInViewConfig.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST),
true, // 在所有当前已经被声明的 Filter 的后面匹配 URL
"/*"
);
}
}
在上面的配置中,我们并没有配置SpringMVC
的DispatcherServlet
,原因是DispatcherServlet
比较特殊,我们可以通过继承WebApplicationInitializer
的抽象实现类AbstractAnnotationConfigDispatcherServletInitializer
来配置它。
WebInitializer
类
package org.junbin.spring.javaconfig.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* @author : Chung Junbin
* @email : <a href="mailto:rekadowney@163.com">发送邮件</a>
* @createDate : 2016-09-01 15:18
* @description :
*/
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/**
* <pre>
* 配置 Spring 的 {@link org.springframework.web.servlet.DispatcherServlet}
* 的 {@code url-pattern}
* </pre>
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
/**
* <pre>
* 配置应用上下文,即所有不包括 SpringMVC 等 Web 配置之外的所有配置,
* 比如:Spring、Hibernate、AOP 等的配置类
* </pre>
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{SpringConfig.class};
}
/**
* <pre>
* 配置 SpringMVC 等 Web 上下文
* </pre>
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{SpringMvcConfig.class};
}
}
接下来演示一下分页功能,首先创建User
实体类。
package org.junbin.spring.javaconfig.domain;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author : Chung Junbin
* @email : <a href="mailto:rekadowney@163.com">发送邮件</a>
* @createDate : 2016-09-01 21:35
* @description :
*/
@Entity
@Table(name = "user")
@Cacheable
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false, updatable = false)
private int id;
@Column(name = "username")
private String username;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "valid")
private boolean valid = true;
public User() {
}
public User(String username, LocalDateTime createTime) {
this.username = username;
this.createTime = createTime;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", createTime=" + createTime +
", valid=" + valid +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public boolean isValid() {
return valid;
}
public void setValid(boolean valid) {
this.valid = valid;
}
}
Repository
接口,相当于DAO
接口,但是使用SpringData
时建议命名为Repository
而不是DAO
。
package org.junbin.spring.javaconfig.repository;
import org.junbin.spring.javaconfig.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author : Chung Junbin
* @email : <a href="mailto:rekadowney@163.com">发送邮件</a>
* @createDate : 2016-09-01 21:40
* @description :
*/
public interface UserRepository extends JpaRepository<User, Integer> {
}
我们只需要简单声明接口即可,SpringData
会自动生成相应的实现类。
跳过Service
业务类,接下来是Controller
类
package org.junbin.spring.javaconfig.controller;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junbin.spring.javaconfig.converter.gson.GsonLocalDateTimeConverter;
import org.junbin.spring.javaconfig.domain.User;
import org.junbin.spring.javaconfig.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.time.LocalDateTime;
/**
* @author : Chung Junbin
* @email : <a href="mailto:rekadowney@163.com">发送邮件</a>
* @createDate : 2016-09-01 22:01
* @description :
*/
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
@Qualifier(value = "userService")
private IUserService userService;
private final Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new GsonLocalDateTimeConverter())
.create();
@RequestMapping(value = "/add", method = RequestMethod.GET)
public ModelAndView add(@RequestParam(value = "name") String name,
@RequestParam(value = "createTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime now) {
userService.save(new User(name, now));
return null;
}
@RequestMapping(value = "/add/and/show", method = RequestMethod.GET)
public String addRedirect(@RequestParam(value = "name") String name,
@RequestParam(value = "createTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime now) {
User user = userService.save(new User(name, now));
return "redirect:/user/" + user.getId() + "/show";
}
@RequestMapping(value = "/{id:\\d+}/delete", method = RequestMethod.GET)
@ResponseBody
public String delete(@PathVariable(value = "id") int id) {
userService.delete(id);
return "{\"status\":200}";
}
@RequestMapping(value = "/{id:\\d+}/show", method = RequestMethod.GET)
@ResponseBody
public String show(@PathVariable(value = "id") int id) {
return gson.toJson(userService.findOne(id));
}
@RequestMapping(value = "/page/{pageOffset:\\d+}/{pageSize:\\d+}", method = RequestMethod.GET)
public String page(@PathVariable(value = "pageOffset") int pageOffset,
@PathVariable(value = "pageSize") int pageSize,
Model model) {
Pageable pageable = new PageRequest(pageOffset, pageSize);
Page<User> userPage = userService.find(pageable);
model.addAttribute("page", userPage);
return "page";
}
}
自己在数据库中插入一些数据或者使用SpringData
提供的批量插入方法或者使用上面Controller
提供的GET
请求插入数据后,我们访问http://localhost/user/page/0/10
即可显示分页信息。如下图:
写作本文只是对Spring
知识的一个补充,基于Java
配置看起来虽然很不错,但是实际上个人并不是十分推崇这种做法。
首先,IDEA
对基于Java
配置的Spring
处理的效果比基于XML
配置的Spring
差很多,比如代码提示——很多快捷的代码提示(诸如视图解析等)没有起作用;比如主动注入——我的IDEA
上在注入UserRepository
时提示没有找到合适的Bean
;还有一些其他的问题。
其次,Hibernate
(JPA
规范的实现厂商)对主键生成策略AUTO
的实现很奇怪,明明已经指定方言为MySQL
了,它依然在生成主键时依然与Hibernate
自动生成的一张存储主键的表(当然,有可能是因为Hibernate5
对主键生成策略的实现不同!)。见下图,自动生成了一个hibernate_sequence
的表来存储user
表的主键值。
最后,一些Spring
的其他功能在基于Java
配置时不起作用,比如自定义的PropertyEditor
,当然包括Spring
原生的PropertyEditor
也不起作用了,因为根本就不需要用到这些配置。从另一方面也可以看成是好处。
原创声明:
本文为个人原创,如有错误与不妥,欢迎提出!
另外,未经许可,谢绝转载。
编写日期:2016-09-06 |
发布日期:2016-09-06 |