spring mvc Spring Data Redis RedisTemplate [转]
http://maven.springframework.org/release/org/springframework/data/spring-data-redis/(spring-data包下载)
Spring-data-redis为spring-data模块中对redis的支持部分,简称为“SDR”,提供了基于jedis客户端API的高度封装以及与spring容器的整合,事实上jedis客户端已经足够简单和轻量级,而spring-data-redis反而具有“过度设计”的嫌疑。
jedis客户端在编程实施方面存在如下不足:
1) connection管理缺乏自动化,connection-pool的设计缺少必要的容器支持。
2) 数据操作需要关注“序列化”/“反序列化”,因为jedis的客户端API接受的数据类型为string和byte,对结构化数据(json,xml,pojo等)操作需要额外的支持。
3) 事务操作纯粹为硬编码
4) pub/sub功能,缺乏必要的设计模式支持,对于开发者而言需要关注的太多。
不过jedis与spring整合,也是非常的简单,参见“jedis连接池实例”.
一. spring-data-redis针对jedis提供了如下功能:
1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
- ValueOperations:简单K-V操作
- SetOperations:set类型数据操作
- ZSetOperations:zset类型数据操作
- HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
3. 提供了对key的“bound”(绑定)便捷化操作API,可以通过bound封装指定的key,然后进行一系列的操作而无须“显式”的再次指定Key,即BoundKeyOperations:
- BoundValueOperations
- BoundSetOperations
- BoundListOperations
- BoundSetOperations
- BoundHashOperations
4. 将事务操作封装,有容器控制。
5. 针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)
- JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。
- StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。
- JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。【需要jackson-mapper-asl工具支持】
- OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】
针对“序列化和发序列化”中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的策略,原则上,我们可以将数据存储为任何格式以便应用程序存取和解析(其中应用包括app,hadoop等其他工具),不过在设计时仍然不推荐直接使用“JacksonJsonRedisSerializer”和“OxmSerializer”,因为无论是json还是xml,他们本身仍然是String。
如果你的数据需要被第三方工具解析,那么数据应该使用StringRedisSerializer而不是JdkSerializationRedisSerializer。
如果你的数据格式必须为json或者xml,那么在编程级别,在redisTemplate配置中仍然使用StringRedisSerializer,在存储之前或者读取之后,使用“SerializationUtils”工具转换转换成json或者xml,请参见下文实例。
6. 基于设计模式,和JMS开发思路,将pub/sub的API设计进行了封装,使开发更加便捷。
7.spring-data-redis中,并没有对sharding提供良好的封装,如果你的架构是基于sharding,那么你需要自己去实现,这也是sdr和jedis相比,唯一缺少的特性。
二.简单实例:
1) spring配置:
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
- <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
- <property name="maxActive" value="32"></property>
- <property name="maxIdle" value="6"></property>
- <property name="maxWait" value="15000"></property>
- <property name="minEvictableIdleTimeMillis" value="300000"></property>
- <property name="numTestsPerEvictionRun" value="3"></property>
- <property name="timeBetweenEvictionRunsMillis" value="60000"></property>
- <property name="whenExhaustedAction" value="1"></property>
- </bean>
- <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
- <property name="poolConfig" ref="jedisPoolConfig"></property>
- <property name="hostName" value="127.0.0.1"></property>
- <property name="port" value="6379"></property>
- <property name="password" value="0123456"></property>
- <property name="timeout" value="15000"></property>
- <property name="usePool" value="true"></property>
- </bean>
- <bean id="jedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
- <property name="connectionFactory" ref="jedisConnectionFactory"></property>
- <property name="keySerializer">
- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
- </property>
- <property name="valueSerializer">
- <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
- </property>
- </bean>
- </beans>
2) 程序实例:
- public class SpringDataRedisTestMain {
- /**
- * @param args
- */
- public static void main(String[] args) {
- ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-redis-beans.xml");
- RedisTemplate redisTemplate = (RedisTemplate)context.getBean("jedisTemplate");
- //其中key采取了StringRedisSerializer
- //其中value采取JdkSerializationRedisSerializer
- ValueOperations<String, User> valueOper = redisTemplate.opsForValue();
- User u1 = new User("zhangsan",12);
- User u2 = new User("lisi",25);
- valueOper.set("u:u1", u1);
- valueOper.set("u:u2", u2);
- System.out.println(valueOper.get("u:u1").getName());
- System.out.println(valueOper.get("u:u2").getName());
- }
- /**
- * 如果使用jdk序列化方式,bean必须实现Serializable,且提供getter/setter方法
- * @author qing
- *
- */
- static class User implements Serializable{
- /**
- *
- */
- private static final long serialVersionUID = -3766780183428993793L;
- private String name;
- private Date created;
- private int age;
- public User(){}
- public User(String name,int age){
- this.name = name;
- this.age = age;
- this.created = new Date();
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Date getCreated() {
- return created;
- }
- public void setCreated(Date created) {
- this.created = created;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- }
- }
3) RedisTemplate:
如果你使用过jedisPool连接池,在数据操作之前,你需要pool.getResource()即从连接池中获取“链接资源”(Jedis),在操作之后,你需要(必须)调用pool.returnResource()将资源归还个连接池。但是,spring-data-redis中,我们似乎并没有直接操作pool,那么spring是如何做到pool管理的呢??一句话:spring的“看门绝技”--callback。
- public <T> T execute(RedisCallback<T> action):这个方法是redisTemplate中执行操作的底层方法,任何基于redisTemplate之上的调用(比如,valueOperations)最终都会被封装成RedisCallback,redisTemplate在execute方法中将会直接使用jedis客户端API进行与server通信,而且在如果使用了连接池,则会在操作之后执行returnSource。
其他实例请参考如下链接:
1) serializer实例
2) operation实例
3) pub/sub实例
一、概念简介:
Redis:
Redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写,详细的信息在Redis官网上面有,因为我自己通过google等各种渠道去学习Redis,走了不少弯路,所以总结一条我认为不错的学习路径给大家:
1.《The Little Redis Book》
是一本开源PDF,只有29页的英文文档,看完后对Redis的基本概念应该差不多熟悉了,剩下的可以去Redis官网熟悉相关的命令。
2.《Redis设计与实现》
如果想继续深入,推荐这本书,现在已经出到第二版了,有纸质版书籍可以购买。上面详细介绍了Redis的一些设计理念,并且给出了一些内部实现方式,和数据结构的C语言定义,有一些基本C语言基础,就能看明白。
3.Redis 2.6源代码:
《Redis设计与实现》的作者发布在Github上的一个开源项目,有作者详细的注释。
https://github.com/huangz1990/annotated_redis_source
Jedis:
Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用。可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis、SRP等等,推荐使用Jedis。
Spring Data Redis
SDR是Spring官方推出,可以算是Spring框架集成Redis操作的一个子框架,封装了Redis的很多命令,可以很方便的使用Spring操作Redis数据库,Spring对很多工具都提供了类似的集成,如Spring Data MongDB…
这三个究竟有什么区别呢?可以简单的这么理解,Redis是用ANSI C写的一个基于内存的Key-Value数据库,而Jedis是Redis官方推出的面向Java的Client,提供了很多接口和方法,可以让Java操作使用Redis,而Spring Data Redis是对Jedis进行了封装,集成了Jedis的一些命令和方法,可以与Spring整合。在后面的配置文件(redis-context.xml)中可以看到,Spring是通过Jedis类来初始化connectionFactory的。
二、Spring Data Redis Demo
项目目录:
Pom.xml配置:
Spring jar因为比较多,就不贴出来了,读者可以下载后面的项目源码查看详细配置,其实pom.xml可以精简,并非一定需要写的这么细,我之所以这么写,是为了看得更清楚。
1 <!-- config junit jar -->
2 <dependency>
3 <groupId>junit</groupId>
4 <artifactId>junit</artifactId>
5 <version>4.8.2</version>
6 <scope>test</scope>
7 </dependency>
8 <!-- config redis data and client jar -->
9 <dependency>
10 <groupId>org.springframework.data</groupId>
11 <artifactId>spring-data-redis</artifactId>
12 <version>1.0.2.RELEASE</version>
13 </dependency>
14 <dependency>
15 <groupId>redis.clients</groupId>
16 <artifactId>jedis</artifactId>
17 <version>2.1.0</version>
18 </dependency>
19
20 <!-- config need jar -->
21 <dependency>
22 <groupId>commons-lang</groupId>
23 <artifactId>commons-lang</artifactId>
24 <version>2.6</version>
25 </dependency>
26 <dependency>
27 <groupId>org.apache.geronimo.specs</groupId>
28 <artifactId>geronimo-servlet_3.0_spec</artifactId>
29 <version>1.0</version>
30 </dependency>
31 <!-- cofig spring jar -->
32 <dependency>
33 <groupId>org.springframework</groupId>
34 <artifactId>spring-core</artifactId>
35 <version>${org.springframework.version}</version>
36 </dependency>
37 ……
redis.properties配置(WEB-INF/property/redis.properties)
从properties文件的内容就知道这个文件是干嘛的了,主要是redis连接池基本配置,详细的配置可以查看redis文档。
redis.host=127.0.0.1
redis.port=6379
redis.pass= redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true
spring-context.xml(WEB-INF/config/spring-context.xml)
Spring配置,这个也没什么说的,就是springMVC的一些基本配置,开启注解扫描功能和扫描路径。
1 <!-- 激活@Controller模式 -->
2 <mvc:annotation-driven />
3
4 <context:annotation-config />
5
6 <!-- 对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->
7 <context:component-scan base-package="com.chr" />
8
9
10 <!-- 引入redis属性配置文件 -->
11 <import resource="redis-context.xml"/>
redis-context.xml(WEB/config/redis-context.xml)
Spring配置redis,这些配置都比较基本,看文档就好了,但是有一个比较重要的点,就是redistemplate的Serializer配置,在后面通过SDR(Spring Data Redis)封装的一些方法操作Redis时会说到。
1 <!-- scanner redis properties -->
2 <context:property-placeholder location="classpath:property/redis.properties" />
3 <!—注意此处注入的是JedisPoolConfig,说明SDR还依赖与Jedis -->
4 <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
5 <property name="maxIdle" value="${redis.maxIdle}" />
6 <property name="maxActive" value="${redis.maxActive}" />
7 <property name="maxWait" value="${redis.maxWait}" />
8 <property name="testOnBorrow" value="${redis.testOnBorrow}" />
9 </bean>
10
11 <bean id="connectionFactory"
12 class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
13 p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"
14 p:pool-config-ref="poolConfig" />
15
16 <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
17 <property name="connectionFactory" ref="connectionFactory" />
18 <!-- 如果不配置Serializer,那么存储的时候智能使用String,如果用User类型存储,那么会提示错误User can't cast to String!!!
19 --> <property name="keySerializer">
20 <bean
21 class="org.springframework.data.redis.serializer.StringRedisSerializer" />
22 </property>
23 <property name="valueSerializer">
24 <bean
25 class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
26 </property>
27 </bean>
28
29 <bean id="viewResolver"
30 class="org.springframework.web.servlet.view.InternalResourceViewResolver" />
web.xml
web.xml中只配置了spring-context.Xml,这是因为我在spring-context.xml中加了一条语句:<import resource="redis-context.xml"/>,所以看起来有两个配置,其实只需要配置spring-context.xml。这样做的好处是:项目的层次比较清晰,方便后期改动。
1 <listener>
2 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
3 </listener>
4
5 <context-param>
6 <param-name>contextConfigLocation</param-name>
7 <param-value>/WEB-INF/config/spring-context.xml</param-value>
8 </context-param>
9
10 <servlet>
11 <servlet-name>SpringMVC</servlet-name>
12 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
13 <init-param>
14 <param-name>contextConfigLocation</param-name>
15 <param-value>/WEB-INF/config/spring-context.xml</param-value>
16 </init-param>
17 <load-on-startup>2</load-on-startup>
18 </servlet>
19
20 <servlet-mapping>
21 <servlet-name>SpringMVC</servlet-name>
22 <url-pattern>/</url-pattern>
23 </servlet-mapping>
下面是Spring MVC的java实现了:
User.java(实体类, com.chr.domain.User.java)
注意User类必须实现Serializable接口,后面会解释。User类总共定义了三个字段:id、name、password。省略了相应的setter/getter方法。
1 public class User implements Serializable {
2 private static final long serialVersionUID = 522889572773714584L;
3
4 private String id;
5 private String name;
6 private String password;
7
8 public User() {}
9
10 public User(String id,String name,String password) {
11 this.id = id;
12 this.name = name;
13 this.password = password;
14 }
UserOperationsService.java(service接口,com.chr.service.UserOperationsService.java)
在service接口中定义了两个方法:
Add方法用于向redis中添加User实例,getUser则从redis中取出User实例。
1 public interface UserOperationsService {
2 void add(User user);
3 User getUser(String key);
4
5 }
UserOperationsServiceImpl.java(service的实现类,实现service借口 com.chr.service.impl. UserOperationsServiceImpl.java)
1 @Service
2 public class UserOperationsServiceImpl implements UserOperationsService {
3 @Autowired
4 private RedisTemplate redisTemplate;
5
6 @Override
7 public void add(User user) {
8 // TODO Auto-generated method stub
9 /*
10 * boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
11 * public Boolean doInRedis(RedisConnection redisConnection) throws
12 * DataAccessException { RedisSerializer<String> redisSerializer =
13 * redisTemplate .getStringSerializer(); byte[] key =
14 * redisSerializer.serialize(user.getId()); byte[] value =
15 * redisSerializer.serialize(user.getName()); return
16 * redisConnection.setNX(key, value); } }); return result;
17 */
18 ValueOperations<String, User> valueops = redisTemplate
19 .opsForValue();
20 valueops.set(user.getId(), user);
21 }
22
23
24 @Override
25 public User getUser(String key) {
26 ValueOperations<String, User> valueops = redisTemplate
27 .opsForValue();
28 User user = valueops.get(key);
29 return user;
30 }
31
32 }
RedisTemplate和 Serializer详解
可以看到我在代码中注释掉了一段代码,现在可以解释上面留下的两个问题了,第一个是在redis.xml中配置redistemplate的时候,同时配置了两个Serializer:keySerializer实现了StringRedisSerializer,valueSerializer实现了JdkSerializationRedisSerializer。
一、为什么要使用Serializer
因为redis是以key-value的形式将数据存在内存中,key就是简单的string,key似乎没有长度限制,不过原则上应该尽可能的短小且可读性强,无论是否基于持久存储,key在服务的整个生命周期中都会在内存中,因此减小key的尺寸可以有效的节约内存,同时也能优化key检索的效率。
value在redis中,存储层面仍然基于string,在逻辑层面,可以是string/set/list/map,不过redis为了性能考虑,使用不同的“encoding”数据结构类型来表示它们。(例如:linkedlist,ziplist等)。
所以可以理解为,其实redis在存储数据时,都把数据转化成了byte[]数组的形式,那么在存取数据时,需要将数据格式进行转化,那么就要用到序列化和反序列化了,这也就是为什么需要配置Serializer的原因。
二、SDR支持的序列化策略:
(详细可查阅API文档)
- JdkSerializationRedisSerializer:
- StringRedisSerializer:
- JacksonJsonRedisSerializer:
- OxmSerializer:
其中JdkSerializationRedisSerializer和StringRedisSerializer是最基础的序列化策略,其中“JacksonJsonRedisSerializer”与“OxmSerializer”都是基于stirng存储,因此它们是较为“高级”的序列化(最终还是使用string解析以及构建java对象)。
基本推荐使用JdkSerializationRedisSerializer和StringRedisSerializer,因为其他两个序列化策略使用起来配置很麻烦,如果实在有需要序列化成Json和XML格式,可以使用java代码将String转化成相应的Json和XML。
三、使用Serializer
在本项目中,是在配置文件中直接配置了相应的Serializer,key用的是StringRedisSerializer,value用的是JdkSerializationRedisSerializer,因为在此项目中,key为userId,为String类型,value为user为java类,即POJO,所以使用JdkSerializationRedisSerializer。
在redistemplate中直接配置Serializer当然比较方便,因为在后面想redis中存取数据时,就不用再次配置Serializer,但是这仅限于只有一种数据类型的情况,比如在本项目中只有<String userId,User user>类型的数据需要存储,如果有多种数据类型时,在配置文件中配置就显得不方便了,那么我们可以在存取数据时,即Service的实现类存取数据操作时分别指定相应的Serializer。
所以在编程时有两种选择:
1.在redistemplate中配置Serializer(本项目即采用这种方式)
ValueOperations<String, User> valueops = redisTemplate
.opsForValue();
valueops.set(user.getId(), user);
2.不在redistemplate中配置Serializer,而是在Service的实现类中单独指定Serializer。就如同UserOperationsServiceImpl.java注释的代码:
1 boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
2 public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {
3 RedisSerializer<String> redisSerializer = redisTemplate .getStringSerializer();
4 byte[] key = redisSerializer.serialize(user.getId());
5 byte[] value = redisSerializer.serialize(user.getName());
6 return redisConnection.setNX(key, value); } });
7 return result;
8 }
四、Redistemplate
SDR官方文档中对Redistemplate的介绍:the template is in fact the central class of the Redis module due to its rich feature set. The template offers a high-level abstraction for Redis interactions.
通过Redistemplate可以调用ValueOperations和ListOperations等等方法,分别是对Redis命令的高级封装。
但是ValueOperations等等这些命令最终是要转化成为RedisCallback来执行的。也就是说通过使用RedisCallback可以实现更强的功能,SDR文档对RedisCallback的介绍:RedisTemplate and StringRedisTemplate allow the developer to talk directly to Redis through the RedisCallback interface. This gives complete control to the developer as it talks directly to the RedisConnection。
具体的使用方法可以参考Api文档。
UserController.java(控制器类,com.chr.controller)
1 @Controller
2 @RequestMapping(value = "/redis")
3 public class UserController {
4 @Autowired
5 private UserOperationsServiceImpl userOperationsService;
6 private User user;
7
8 @RequestMapping(value = "/addUser", method = RequestMethod.POST)
9 public String addUser(
10 @RequestParam(value = "Id", required = true) String Id,
11 @RequestParam(value = "name", required = true) String name,
12 @RequestParam(value = "password", required = true) String password) {
13 user = new User(Id, name, password);
14 userOperationsService.add(user);
15 return "/WEB-INF/jsp/AddUserSuccess.jsp";
16 }
17
18 @RequestMapping(value = "/addUser", method = RequestMethod.GET)
19 public String addUser() {
20 return "/WEB-INF/jsp/AddUser.jsp";
21 }
22 }
这里只贴出了部分代码(addUser的代码),剩下的getUser代码类似,可以下载源码查看。
其中分为两种方法,get和post,get方法直接return到表单填写页面,从而实现post到addUser添加User。
AddUser.jsp
<form id="addUser" name="addUser" action="redis/addUser" method="post">
ID:<input id="Id" name="Id" type="text" /><br/>
Name:<input id="name" name="name" type="text" /><br/>
Password:<input id="password" name="password" type="password" /><br/>
<input value="添加"
type="submit" />
</form>
三、部署运行
最后部署到Tomcat中,浏览器运行:http://localhost:8080/redis-web/redis/addUser
填写信息,单击添加Button后,即跳转到结果页面
整个项目只是一个展示Spring整合Redis基本使用的Demo,因本人知识有限,如文中有错误或偏颇之处,请各位提出。非常感谢:)
四、项目源码:
http://files.cnblogs.com/edwinchen/redis-web.rar
spring mvc Spring Data Redis RedisTemplate [转]的更多相关文章
- spring data redis RedisTemplate操作redis相关用法
http://blog.mkfree.com/posts/515835d1975a30cc561dc35d spring-data-redis API:http://docs.spring.io/sp ...
- SSM 即所谓的 Spring MVC + Spring + MyBatis 整合开发。
SSM 即所谓的 Spring MVC + Spring + MyBatis 整合开发.是目前企业开发比较流行的架构.代替了之前的SSH(Struts + Spring + Hibernate) 计划 ...
- Spring MVC+Spring +Hibernate配置事务,但是事务不起作用
最近做项目,被一个问题烦恼了很久.使用Spring MVC+Spring +Hibernate开发项目,在使用注解配置事务管理,刚开始发现无论如何数据库都无法更新,但是可以从数据库查询到数据.怀疑是配 ...
- freemarker + spring mvc + spring + mybatis + mysql + maven项目搭建
今天说说搭建项目,使用freemarker + spring mvc + spring + mybatis + mysql + maven搭建web项目. 先假设您已经配置好eclipse的maven ...
- Spring MVC + Spring + Mybitis开发Java Web程序基础
Spring MVC + Spring + Mybitis是除了SSH外的另外一种常见的web框架组合. Java web开发和普通的Java应用程序开发是不太一样的,下面是一个Java web开发在 ...
- Spring MVC+Spring+Mybatis+MySQL(IDEA)入门框架搭建
目录 Spring MVC+Spring+Mybatis+MySQL(IDEA)入门框架搭建 0.项目准备 1.数据持久层Mybatis+MySQL 1.1 MySQL数据准备 1.2 Mybatis ...
- velocity+spring mvc+spring ioc+ibatis初试感觉(与struts+spring+hibernate比较)
velocity+spring mvc+spring ioc+ibatis框架是我现在公司要求采用的,原因是因为阿里巴巴和淘宝在使用这样的框架,而我公司现在还主要是以向阿里巴巴和淘宝输送外派人员为 主 ...
- Spring MVC -- Spring MVC入门
本篇博客首先介绍Spring MVC的优点,然后介绍Spring MVC的基本组件,包括DispatcherServlet,并学习如何开发一个“传统风格”的控制器,这是在Spring 2.5版本之前开 ...
- 基于Spring MVC + Spring + MyBatis的【医院就诊挂号系统】
资源下载:https://download.csdn.net/download/weixin_44893902/21727306 一.语言和环境 1.实现语言: JAVA语言. 2.环境要求: MyE ...
随机推荐
- Web.xml配置详解之context-param(转)
本文转自:http://blog.csdn.net/liaoxiaohua1981/article/details/6759206 格式定义: <context-param> <pa ...
- [状压dp]HDU5045 Contest
题意: n和人做m道题, 每俩人做的题数不能相差一题以上.(也就是每n道题分别由n个人完成) 给n个人分别做m道题的概率, 求完成m题的最大期望 $1\le N \le 10$ 注意!!! fil ...
- 李洪强iOS开发之-PCH文件的配置
pch 可以用来存储共享信息,比如设备屏幕的宽度,高度.版本号等等 公用信息 Xcode 老版本会自动为我们创建pch文件,新版本开始不自动创建了,如果需要使用可以自己手动创建 创建完成后可以在里面定 ...
- 滑动RecyclerView时出现异常: java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 6(offset:6).state:30
RecyclerView 存在的一个明显的 bug 一直没有修复: java.lang.IndexOutOfBoundsException: Inconsistency detected. Inval ...
- Android 三档自定义滑动开关,禁止点击功能的实现,用默认的seekbar组件实现
android三档自定义滑动开关,禁止点击功能的实现,普通开关网上有很多例子,三档滑动开关的则找了整天都没有相关例子,开始用普通开关的源码修改了自己实现了一个类,但效果不如人意,各种边界情况的算法很难 ...
- 【HDOJ】2155 小黑的镇魂曲
线段树+SPFA最短路可以过.或者DP也能过.需要注意的是xl的范围是错的,测试用例中xl可能为0,他妈的,因为这个一直莫名其妙的wa.1. spfa建图增加一倍的点即可(讨论左端点和右端点). /* ...
- 【HDOJ】1058 Humble Numbers
简单题,注意打表,以及输出格式.这里使用了可变参数. #include <stdio.h> #define MAXNUM 5845 #define ANS 2000000000 int b ...
- Awesomplete 屌爆了
自动完成,功能强大! 具体请参考 http://leaverou.github.io/awesomplete
- Hibernate: org.hibernate.exception.SQLGrammarException: could not insert: 错误
最近在学习Java Web,今天刚接触Hibernate.学习的书籍是<轻量级Java EE企业应用实战(第3版)>.书中367页5.2.2中给予的Hibernate例子中的代码运行有以下 ...
- 使用 jQuery 进行前端验证 -- 1
如今很多的网站偶会有不同层次的验证去验证用户输入的信息是否符合我们所需要的数据类型.并且可以说任何有输入的地方都需要的去验证,验证一方面是要求用户输入正确格式的数据,同时也是避免恶意的用户进行非法的输 ...