Spring4.1新特性——Spring MVC增强

1、GroovyWebApplicationContext 

在Spring 4.1之前没有提供Web集成的ApplicationContext,在《Spring4新特性——Groovy Bean定义DSL》中我们自己去实现的com.sishuok.spring4.context.support.WebGenricGroovyApplicationContext,而4.1其已经提供了相应实现,直接把《Spring4新特性——Groovy Bean定义DSL》配置中的相应类改掉即可。

2、视图解析器标签

之前我们都是这样定义视图解析器:

Java代码  

  1. <bean id="mvcVelocityEngine" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
  2. <property name="resourceLoaderPath" value="/WEB-INF/vm/,classpath:com/github/zhangkaitao" />
  3. </bean>
  4. <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
  5. <property name="prefix" value=""/>
  6. <property name="suffix" value=".vm"/>
  7. <property name="cache" value="false"/>
  8. </bean>
    <bean id="mvcVelocityEngine" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath" value="/WEB-INF/vm/,classpath:com/github/zhangkaitao" />
    </bean>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        <property name="prefix" value=""/>
        <property name="suffix" value=".vm"/>
        <property name="cache" value="false"/>
    </bean>

而现在我们可以使用MVC标签定义:

Java代码  

  1. <mvc:velocity-configurer resource-loader-path="/WEB-INF/vm/,classpath:com/github/zhangkaitao"/>
  2. <mvc:view-resolvers>
  3. <mvc:velocity cache-views="false" prefix="" suffix=".vm"/>
  4. </mvc:view-resolvers>
    <mvc:velocity-configurer resource-loader-path="/WEB-INF/vm/,classpath:com/github/zhangkaitao"/>
    <mvc:view-resolvers>
        <mvc:velocity cache-views="false" prefix="" suffix=".vm"/>
    </mvc:view-resolvers>

再来看一个更复杂的例子:

Java代码  

  1. <mvc:velocity-configurer resource-loader-path="/WEB-INF/vm/,classpath:com/github/zhangkaitao"/>
  2. <mvc:groovy-configurer resource-loader-path="classpath:templates/" cache-templates="false"/>
  3. <mvc:view-resolvers>
  4. <mvc:content-negotiation>
  5. <mvc:default-views>
  6. <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
  7. <property name="jsonpParameterNames">
  8. <set>
  9. <value>jsonp</value>
  10. <value>callback</value>
  11. </set>
  12. </property>
  13. </bean>
  14. </mvc:default-views>
  15. </mvc:content-negotiation>
  16. <mvc:velocity cache-views="false" prefix="" suffix=".vm"/>
  17. <mvc:groovy cache-views="false" suffix=".tpl"/>
  18. </mvc:view-resolvers>
    <mvc:velocity-configurer resource-loader-path="/WEB-INF/vm/,classpath:com/github/zhangkaitao"/>
    <mvc:groovy-configurer resource-loader-path="classpath:templates/" cache-templates="false"/>
    <mvc:view-resolvers>
        <mvc:content-negotiation>
            <mvc:default-views>
                <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
                    <property name="jsonpParameterNames">
                        <set>
                            <value>jsonp</value>
                            <value>callback</value>
                        </set>
                    </property>
                </bean>
            </mvc:default-views>
        </mvc:content-negotiation>
        <mvc:velocity cache-views="false" prefix="" suffix=".vm"/>
        <mvc:groovy cache-views="false" suffix=".tpl"/>
    </mvc:view-resolvers>

mvc:content-negotiation用于定义内容协商的视图解析器,且内部可以定义默认视图;然后我们又定义了mvc:velocity和mvc:groovy两个视图解析器;它们会按照顺序进行解析。另外几个视图解析器是:

mvc:freemarker

mvc:bean-name

mvc:jsp

这种方式有一个很大的问题就是只能做默认配置,如果想自定义其属性值就搞不定了,估计当时开发的人考虑不全或没有经验。

3、控制器标签

Spring 4.1提供了更丰富的控制器标签:

3.1、重定向视图控制器标签

Java代码  

  1. <mvc:redirect-view-controller
  2. path="/redirect"
  3. redirect-url="/status"
  4. context-relative="true"
  5. status-code="301"
  6. keep-query-params="true"/>
    <mvc:redirect-view-controller
            path="/redirect"
            redirect-url="/status"
            context-relative="true"
            status-code="301"
            keep-query-params="true"/>

3.2、状态控制器标签

Java代码  

  1. <mvc:status-controller path="/status" status-code="200"/>
    <mvc:status-controller path="/status" status-code="200"/>

3.3、带状态的视图控制器标签

Java代码  

  1. <mvc:view-controller path="/error/**" status-code="200"/>
    <mvc:view-controller path="/error/**" status-code="200"/>

4、Groovy Template引擎集成

Spring 4.1提供了对Groovy Template模板引擎的集成,其是一种DSL风格的模板引擎,其也是最早在Spring Boot中引入的。

4.1、Spring配置文件

Java代码  

  1. <mvc:groovy-configurer resource-loader-path="classpath:templates/" cache-templates="false"/>
  2. <mvc:view-resolvers>
  3. <mvc:groovy cache-views="false" suffix=".tpl"/>
  4. </mvc:view-resolvers>
    <mvc:groovy-configurer resource-loader-path="classpath:templates/" cache-templates="false"/>
    <mvc:view-resolvers>
        <mvc:groovy cache-views="false" suffix=".tpl"/>
    </mvc:view-resolvers>

4.2、模板heelo.tpl

Java代码  

  1. yieldUnescaped ‘<!DOCTYPE html>‘
  2. html {
  3. head {
  4. title(‘hello groovy templates‘)
  5. }
  6. body {
  7. div("hello $user.name")
  8. }
  9. }
yieldUnescaped ‘<!DOCTYPE html>‘
html {
  head {
    title(‘hello groovy templates‘)
  }
  body {
      div("hello $user.name")
  }
}

具体语法请参考官方文档。

5、 Jackson @JsonView支持

可以使用@JsonView来分组渲染JSON数据,按需展示JSON数据。

5.1、模型

Java代码  

  1. public class User implements Serializable {
  2. public static interface OnlyIdView {}
  3. public static interface OnlyNameView {}
  4. public static interface AllView extends OnlyIdView, OnlyNameView {}
  5. @JsonView(OnlyIdView.class)
  6. private Long id;
  7. @JsonView(OnlyNameView.class)
  8. private String name;
  9. ……
  10. }
public class User implements Serializable {
    public static interface OnlyIdView {}
    public static interface OnlyNameView {}
    public static interface AllView extends OnlyIdView, OnlyNameView {}

    @JsonView(OnlyIdView.class)
    private Long id;

    @JsonView(OnlyNameView.class)
    private String name;  
    ……
}

定义了三个视图:OnlyIdView、OnlyNameView和AllView。

5.2、控制器

Java代码  

  1. @RestController
  2. public class JacksonJsonViewController {
  3. @RequestMapping("/jackson1")
  4. @JsonView(User.OnlyIdView.class)
  5. public User test1() {
  6. return new User(1L, "zhangsan");
  7. }
  8. @RequestMapping("/jackson2")
  9. @JsonView(User.OnlyNameView.class)
  10. public User test2() {
  11. return new User(1L, "zhangsan");
  12. }
  13. @RequestMapping("/jackson3")
  14. @JsonView(User.AllView.class) //可以省略
  15. public User test3() {
  16. return new User(1L, "zhangsan");
  17. }
  18. }
@RestController
public class JacksonJsonViewController {

    @RequestMapping("/jackson1")
    @JsonView(User.OnlyIdView.class)
    public User test1() {
        return new User(1L, "zhangsan");
    }

    @RequestMapping("/jackson2")
    @JsonView(User.OnlyNameView.class)
    public User test2() {
        return new User(1L, "zhangsan");
    }

    @RequestMapping("/jackson3")
    @JsonView(User.AllView.class) //可以省略
    public User test3() {
        return new User(1L, "zhangsan");
    }
}

使用@JsonView控制渲染哪些数据。

6、Jsonp支持

6.1、MappingJackson2JsonView提供的支持

Java代码  

  1. <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
  2. <property name="jsonpParameterNames">
  3. <set>
  4. <value>jsonp</value>
  5. <value>callback</value>
  6. </set>
  7. </property>
  8. </bean>
    <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
        <property name="jsonpParameterNames">
            <set>
                <value>jsonp</value>
                <value>callback</value>
            </set>
       </property>
    </bean>

然后访问如http://localhost:8080/json?callback=callback即可得到JSONP响应:callback({"user":{"id":1,"name":"zhangsan"}});。

6.2、对使用HttpMessageConverter的@ResponseBody的支持

Java代码  

  1. @Order(2)
  2. @ControllerAdvice(basePackages = "com.github")
  3. public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
  4. public JsonpAdvice() {
  5. super("callback", "jsonp"); //指定jsonpParameterNames
  6. }
  7. }
@Order(2)
@ControllerAdvice(basePackages = "com.github")
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
    public JsonpAdvice() {
        super("callback", "jsonp"); //指定jsonpParameterNames
    }
}

访问http://localhost:8080/jackson1?callback=callback即可看到JSONP响应。

@ContollerAdvice的作用请参考《Spring3.2新注解@ControllerAdvice》,basePackages用于指定对哪些包里的Controller起作用。

6.3、ResponseBodyAdvice

我们之前实现的JsonpAdvice其继承自AbstractJsonpResponseBodyAdvice,而AbstractJsonpResponseBodyAdvice继承自ResponseBodyAdvice,其作用是在响应体写出之前做一些处理:

Java代码  

  1. @Order(1)
  2. @ControllerAdvice(basePackages = "com.github")
  3. public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> {
  4. @Override
  5. public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
  6. return methodParameter.getMethod().getReturnType().isAssignableFrom(User.class);
  7. }
  8. @Override
  9. public Object beforeBodyWrite(
  10. Object obj, MethodParameter methodParameter, MediaType mediaType,
  11. Class<? extends HttpMessageConverter<?>> converterType,
  12. ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
  13. User user = ((User)obj);
  14. user.setName("---" + user.getName() + "---");
  15. return user;
  16. }
  17. }
@Order(1)
@ControllerAdvice(basePackages = "com.github")
public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
        return methodParameter.getMethod().getReturnType().isAssignableFrom(User.class);
    }

    @Override
    public Object beforeBodyWrite(
            Object obj, MethodParameter methodParameter, MediaType mediaType,
            Class<? extends HttpMessageConverter<?>> converterType,
            ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        User user = ((User)obj);
        user.setName("---" + user.getName() + "---");
        return user;
    }
}

1、supports指定支持哪些类型的方法进行处理,此处是返回值为User的;2、我们得到User对象然后在名字前后拼上”---“ ;3、可以指定多个ResponseBodyAdvice,使用@Order指定顺序。访问http://localhost:8080/jackson2?callback=callback可以看到效果。

7、Gson HttpMessageConverter

7.1、Spring配置

Java代码  

  1. <mvc:annotation-driven>
  2. <mvc:message-converters>
  3. <bean class="org.springframework.http.converter.json.GsonHttpMessageConverter"/>
  4. </mvc:message-converters>
  5. </mvc:annotation-driven>
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.GsonHttpMessageConverter"/>
        </mvc:message-converters>
    </mvc:annotation-driven>

使用方式和Jackson Json类似。本文使用的是<gson.version>2.2.4</gson.version>版本。

8、Protobuf HttpMessageConverter

8.1、Spring配置

Java代码  

  1. <mvc:annotation-driven>
  2. <mvc:message-converters>
  3. <bean class="org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter">
  4. <constructor-arg>
  5. <bean class="com.github.zhangkaitao.web.controller.MyExtensionRegistryInitializer"/>
  6. </constructor-arg>
  7. </bean>
  8. </mvc:message-converters>
  9. </mvc:annotation-driven>
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter">
                <constructor-arg>
                    <bean class="com.github.zhangkaitao.web.controller.MyExtensionRegistryInitializer"/>
                </constructor-arg>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

8.2、定义protobuf message(proto/user.proto)

Java代码  

  1. package com.github.zhangkaitao.pb;
  2. option java_package = "com.github.zhangkaitao.pb";
  3. option java_outer_classname = "UserProtos";
  4. message User {
  5. optional int64 id = 1;
  6. optional string name = 2;
  7. }
package com.github.zhangkaitao.pb;
 
 option java_package = "com.github.zhangkaitao.pb";
 option java_outer_classname = "UserProtos";
 
 message User {
   optional int64 id = 1;
   optional string name = 2;
 }

8.3、添加maven插件自动把protobuf message转化成Java代码

Java代码  

  1. <plugin>
  2. <groupId>com.google.protobuf.tools</groupId>
  3. <artifactId>maven-protoc-plugin</artifactId>
  4. <version>0.1.10</version>
  5. <executions>
  6. <execution>
  7. <id>generate-sources</id>
  8. <goals>
  9. <goal>compile</goal>
  10. </goals>
  11. <phase>generate-sources</phase>
  12. <configuration>
  13. <protoSourceRoot>${basedir}/src/main/proto/</protoSourceRoot>
  14. <includes>
  15. <param>**/*.proto</param>
  16. </includes>
  17. </configuration>
  18. </execution>
  19. </executions>
  20. <configuration>
  21. <protocExecutable>D:/software/protoc.exe</protocExecutable>
  22. </configuration>
  23. </plugin>
            <plugin>
                <groupId>com.google.protobuf.tools</groupId>
                <artifactId>maven-protoc-plugin</artifactId>
                <version>0.1.10</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <phase>generate-sources</phase>
                        <configuration>
                            <protoSourceRoot>${basedir}/src/main/proto/</protoSourceRoot>
                            <includes>
                                <param>**/*.proto</param>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
                <configuration>
                    <protocExecutable>D:/software/protoc.exe</protocExecutable>
                </configuration>
            </plugin>

8.4、测试控制器

Java代码  

  1. @RestController
  2. public class ProtobufController {
  3. @RequestMapping("/proto/read")
  4. public ResponseEntity<UserProtos.User> protoRead() {
  5. return ResponseEntity.ok(UserProtos.User.newBuilder().setId(1).setName("zhangsan").build());
  6. }
  7. @RequestMapping("/proto/write")
  8. public ResponseEntity<UserProtos.User> protoRead(RequestEntity<UserProtos.User> requestEntity) {
  9. System.out.println("server===\n" + requestEntity.getBody());
  10. return ResponseEntity.ok(requestEntity.getBody());
  11. }
  12. }
@RestController
public class ProtobufController {
    @RequestMapping("/proto/read")
    public ResponseEntity<UserProtos.User> protoRead() {
        return ResponseEntity.ok(UserProtos.User.newBuilder().setId(1).setName("zhangsan").build());
    }
    @RequestMapping("/proto/write")
    public ResponseEntity<UserProtos.User> protoRead(RequestEntity<UserProtos.User> requestEntity) {
        System.out.println("server===\n" + requestEntity.getBody());
        return ResponseEntity.ok(requestEntity.getBody());
    }
}

8.5、测试用例(com.github.zhangkaitao.proto.ProtoTest)

Java代码  

  1. @Test
  2. public void testRead() {
  3. HttpHeaders headers = new HttpHeaders();
  4. RequestEntity<UserProtos.User> requestEntity =
  5. new RequestEntity<UserProtos.User>(headers, HttpMethod.POST, URI.create(baseUri + "/proto/read"));
  6. ResponseEntity<UserProtos.User> responseEntity =
  7. restTemplate.exchange(requestEntity, UserProtos.User.class);
  8. System.out.println(responseEntity.getBody());
  9. }
  10. @Test
  11. public void testWrite() {
  12. UserProtos.User user = UserProtos.User.newBuilder().setId(1).setName("zhangsan").build();
  13. HttpHeaders headers = new HttpHeaders();
  14. RequestEntity<UserProtos.User> requestEntity =
  15. new RequestEntity<UserProtos.User>(user, headers, HttpMethod.POST, URI.create(baseUri + "/proto/write"));
  16. ResponseEntity<UserProtos.User> responseEntity =
  17. restTemplate.exchange(requestEntity, UserProtos.User.class);
  18. System.out.println(responseEntity.getBody());
  19. }
    @Test
    public void testRead() {
        HttpHeaders headers = new HttpHeaders();
        RequestEntity<UserProtos.User> requestEntity =
                new RequestEntity<UserProtos.User>(headers, HttpMethod.POST, URI.create(baseUri + "/proto/read"));

        ResponseEntity<UserProtos.User> responseEntity =
                restTemplate.exchange(requestEntity, UserProtos.User.class);

        System.out.println(responseEntity.getBody());
    }

    @Test
    public void testWrite() {
        UserProtos.User user = UserProtos.User.newBuilder().setId(1).setName("zhangsan").build();
        HttpHeaders headers = new HttpHeaders();
        RequestEntity<UserProtos.User> requestEntity =
                new RequestEntity<UserProtos.User>(user, headers, HttpMethod.POST, URI.create(baseUri + "/proto/write"));

        ResponseEntity<UserProtos.User> responseEntity =
                restTemplate.exchange(requestEntity, UserProtos.User.class);
        System.out.println(responseEntity.getBody());
    }

测试用例知识请参考《Spring MVC测试框架详解——服务端测试》和《Spring MVC测试框架详解——客户端测试》。

测试过程中会抛出:

Java代码  

  1. Caused by: java.lang.UnsupportedOperationException
  2. at java.util.Collections$UnmodifiableMap.put(Collections.java:1342)
  3. at org.springframework.http.HttpHeaders.set(HttpHeaders.java:869)
  4. at org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter.setProtoHeader(ProtobufHttpMessageConverter.java:196)
Caused by: java.lang.UnsupportedOperationException
	at java.util.Collections$UnmodifiableMap.put(Collections.java:1342)
	at org.springframework.http.HttpHeaders.set(HttpHeaders.java:869)
	at org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter.setProtoHeader(ProtobufHttpMessageConverter.java:196)

这是因为ProtobufHttpMessageConverter会修改响应头,但是ResponseEntity构造时HttpHeaders是不允许修改的。暂时解决办法是注释掉:

Java代码  

  1. //setProtoHeader(outputMessage, message);
//setProtoHeader(outputMessage, message);

9、RequestEntity/ResponseEntity

Spring 4.1提供了ResponseEntity配对的RequestEntity,使用方式和HttpEntity一样。具体可以参考com.github.zhangkaitao.web.controller.RequestResponseEntityController。

10、MvcUriComponentsBuilder

其作用可以参考《Spring4新特性——注解、脚本、任务、MVC等其他特性改进》,Spring 4.1又提供了一个新的方法MvcUriComponentsBuilder.fromMappingName用于根据控制器方法来生成请求URI。

Java代码  

  1. @RestController
  2. public class MvcUriComponentsBuilderController {
  3. @RequestMapping("/uri")
  4. public String mvcUriComponentsBuilder1() {
  5. return MvcUriComponentsBuilder.fromMappingName("MUCBC#mvcUriComponentsBuilder1").build();
  6. }
  7. @RequestMapping("/uri/{id}")
  8. public String mvcUriComponentsBuilder2(@PathVariable Long id) {
  9. return MvcUriComponentsBuilder.fromMappingName("MUCBC#mvcUriComponentsBuilder2").arg(0, "123").build();
  10. }
  11. }
@RestController
public class MvcUriComponentsBuilderController {

    @RequestMapping("/uri")
    public String mvcUriComponentsBuilder1() {
        return MvcUriComponentsBuilder.fromMappingName("MUCBC#mvcUriComponentsBuilder1").build();
    }
    @RequestMapping("/uri/{id}")
    public String mvcUriComponentsBuilder2(@PathVariable Long id) {
        return MvcUriComponentsBuilder.fromMappingName("MUCBC#mvcUriComponentsBuilder2").arg(0, "123").build();
    }
}

规则是“控制器所有大写字母#方法名”找到相应的方法。 另外可以直接在页面中使用如下方式获取相应的URI:

Java代码  

  1. ${s:mvcUrl(‘MUCBC#mvcUriComponentsBuilder2‘).arg(0,"123").build()}
${s:mvcUrl(‘MUCBC#mvcUriComponentsBuilder2‘).arg(0,"123").build()}

如上方式只能在正常EL 3.0的容器中运行,可参考《Expression Language 3.0新特性》。

11、MockRestServiceServer

MockRestServiceServer目前提供了对AsyncRestTemplate的支持,使用方式和RestTemplate一样。可参考《Spring MVC测试框架详解——客户端测试》。

12、MockMvcConfigurer

Spring 4.1提供了MockMvcConfigurer用于进行一些通用配置,使用方式如下:

Java代码  

  1. mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(defaultSetup()).build();
mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(defaultSetup()).build();

MockMvcConfigurer实现:

Java代码  

  1. private MockMvcConfigurer defaultSetup() {
  2. return new MockMvcConfigurer() {
  3. @Override
  4. public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> configurableMockMvcBuilder) {
  5. configurableMockMvcBuilder.alwaysExpect(status().isOk());
  6. }
  7. @Override
  8. public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> configurableMockMvcBuilder, WebApplicationContext webApplicationContext) {
  9. return new RequestPostProcessor() {
  10. @Override
  11. public MockHttpServletRequest postProcessRequest(MockHttpServletRequest mockHttpServletRequest) {
  12. mockHttpServletRequest.setAttribute("aa", "aa");
  13. return mockHttpServletRequest;
  14. }
  15. };
  16. }
  17. };
  18. }
    private MockMvcConfigurer defaultSetup() {
        return new MockMvcConfigurer() {
            @Override
            public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> configurableMockMvcBuilder) {
                configurableMockMvcBuilder.alwaysExpect(status().isOk());
            }
            @Override
            public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> configurableMockMvcBuilder, WebApplicationContext webApplicationContext) {
                return new RequestPostProcessor() {
                    @Override
                    public MockHttpServletRequest postProcessRequest(MockHttpServletRequest mockHttpServletRequest) {
                        mockHttpServletRequest.setAttribute("aa", "aa");
                        return mockHttpServletRequest;
                    }
                };
            }
        };
    }

可以在如上实现中进行一些通用配置,如安全(往Request中扔安全对象之类的)。测试用例可参考com.github.zhangkaitao.proto.ProtoTest2。

时间: 2024-10-26 12:39:11

Spring4.1新特性——Spring MVC增强的相关文章

Spring4.1新特性——Spring缓存框架增强(转)

目录 Spring4.1新特性——综述 Spring4.1新特性——Spring核心部分及其他 Spring4.1新特性——Spring缓存框架增强 Spring4.1新特性——异步调用和事件机制的异常处理 Spring4.1新特性——数据库集成测试脚本初始化 Spring4.1新特性——Spring MVC增强 Spring4.1新特性——页面自动化测试框架Spring MVC Test HtmlUnit简介 Spring4.1新特性——静态资源处理增强 Spring 4.1提供了对jcach

Oracle12c中数据泵新特性之功能增强(expdp, impdp)

Oracle12c中数据泵新特性之功能增强(expdp, impdp) Oracle的数据泵功能在10g中被引进.本文对数据泵在12c中的增强做一个概览. 1.   禁用日志选项(DISABLE_ARCHIVE_LOGGING) Impdp的TRANSFORM参数已经扩展为包括DISABLE_ARCHIVE_LOGGING选项.该选项的默认值为 "N",不会影响日志行为.将该选项设置为"Y",这将会使表和索引在导入前将日指属性设置为NOLOGGING,从而导入期间减

Spring4.2新特性(一)

已经发在了并发编程网: http://ifeve.com/spring4-2/ 1. 简介. 前些天spring4.2出来了, 从GA开始就一直在跟了, 前2天看完了所有Release Notes, 觉得记录下我比较感兴趣的特性. 官方的Release Notes: https://jira.spring.io/browse/SPR?selectedTab=com.atlassian.jira.jira-projects-plugin:changelog-panel&allVersions=tr

JAVA8新特性——接口定义增强

JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ 接口定义增强 在JDK1.8以前,接口是定义的: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法. 在JDK1.8之前,接口有如下特性: 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错). 接口中

spring4的新特性---泛型注入

废话不多说,直接上代码 一.写一个实体类 package generic; import java.io.Serializable; public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private String name; private int age; public String getName() { return name; } pub

Spring4.x新特性

最近项目中准备集成Spring Data Redis, <dependencies>     <dependency>         <groupId>org.springframework.data</groupId>         <artifactId>spring-data-redis</artifactId>         <version>1.7.1.RELEASE</version>    

Java 8新特性-接口定义增强

为了解决当原有的接口中方法不足时,向原有的接口中添加新的方法,该接口下的N多实现类也需要重写该方法的问题!Java8引入了接口定义增强概念! Java8 打破了原有的接口的方法定义: 公共的.抽象的  默认方法: Java 8 还允许我们给接口添加一个非抽象的方法实现,只需要使用 default 关键字即可,这个特征又叫做扩展方法. 在实现该接口时,该默认扩展方法在子类上可以直接使用,它的使用方式类似于抽象类中非抽象成员方法. 但扩展方法不能够重载 Object 中的方法.例如:toString

Java SE 6 新特性: HTTP 增强--转

概述 Java 语言从诞生的那天起,就非常注重网络编程方面的应用.随着互联网应用的飞速发展,Java 的基础类库也不断地对网络相关的 API 进行加强和扩展.在 Java SE 6 当中,围绕着 HTTP 协议出现了很多实用的新特性:NTLM 认证提供了一种 Window 平台下较为安全的认证机制:JDK 当中提供了一个轻量级的 HTTP 服务器:提供了较为完善的 HTTP Cookie 管理功能:更为实用的 NetworkInterface:DNS 域名的国际化支持等等. NTLM 认证 不可

Oracle 11g新特性延迟段创建和truncate的增强

下面测试Oracle 11g开始的新特性truncate的增强和延迟段空间创建. Oracle从11g开始,当用户创建一张空表的时候不会先分配段和空间,只有当对这张表插入第一行数据的时候才分配段和空间. 这就解决了有很多表是空的但是占用大量的磁盘空间.   测试11g延迟段创建和truncate 用户下有一张新表 SQL> select * from tab; TNAME TABTYPE CLUSTERID ------------------------------ ------- -----