Spring之Spring注解与数据绑定

本文主要总结Spring 常用注解,数据绑定,以及最为常见的接口请求的,Json数据下发,以及拦截器的常规使用。

Spring 常用注解

  • @Controller(控制器,注入服务)

    Controller 注解是用于标记一个类上,使用它标记的类就是一个SpringMVC Controller对象。是一个控制器对象,这个类中方法就是具体的动作。一般是暴露出去的请求的定义。

  • @RequestMapping

    是用来处理请求地址映射的注解,可以用于类火方法上。用于类上,标识类中的所有响应请求的方法是以该地址做为父路径。所以下面的地址是http://localhost:8080/parent.html/acdc

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @Controller
    @RequestMapping(value = "parent.html")
    public class HelloController {

    @RequestMapping(value = "acdc")
    public String hello(){
    return "hello ,this is a ACDC demo";
    }
    }
  • @Service 服务(注入Dao)

    Service注解是告诉Spring,当Spring要创建UserServiceImpl的实例时,bean的名字必须交”userService”,这样当Action需要使用UserServiceImpl的实例时,就可以由Spring创建好的userService,然后注入给Action。

  • @Repository (实现Dao)

    其实就是Dao的实现。

  • @Component

    把普通实例化到Spring容器中,相当于配置文件中的<bean id=”” class = “”/

  • @Autowired(依赖注入组件)

    就是自动装配,其作用是为了消除代码Java代码里面的getter/setter与bean属性中的property。getter看个人需求,如果私有属性需要对外提供的话,应当予以保留。

  • @ResponseBody

    作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML。在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。

  • @RestController

    RestController注解相当于@Controller和@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了,使用这个注解不能返回jsp和html页面,视图解析器无法解析。

  • @Resource

    @Resource和@AutoWired比较类似,@Resource后面没有任何内容。两者的区别@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配。@Autowired是Spring的注解,@Resource是J2EE的注解,Spring属于第三方的,J2EE是Java自己的东西,因此,建议使用@Resource注解,以减少代码和Spring之间的耦合。

  • @JsonIgnoreProperties

    将这个注解写在类上之后,就会忽略类中不存在的字段,可以满足当前的需要。

三种常规接口

返回的index,是返回jsp页面的名称

  1. 字符串参数来处理。请求地址(http://localhost:8080/home/index?homeId=4777)

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(@RequestParam("homeId") Integer homeId, Model model) {
    log.debug("This is a out put homeId = {}", homeId);
    Home home = homeService.getHomeById(homeId);
    model.addAttribute(home);
    return "index";
    }
  2. 使用路径变量来处理。请求地址(http://localhost:8080/home/index2/5666)

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping(value = "/index2/{homeId}", method = RequestMethod.GET)
    public String index2(@PathVariable("homeId") Integer homeId, Map<String, Object> map) {
    log.debug("This is a out put homeId = {}", homeId);
    Home home = homeService.getHomeById(homeId);
    map.put("home", home);
    return "index";
    }
  1. 使用HttpServletRequest处理。请求地址(http://localhost:8080/home/index3?homeId=333)

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping(value = "index3", method = RequestMethod.GET)
    public String index3(HttpServletRequest httpServletRequest) {
    Integer homeId = Integer.valueOf(httpServletRequest.getParameter("homeId"));
    Home home = homeService.getHomeById(homeId);
    httpServletRequest.setAttribute("home", home);
    return "index";
    }

Binding

将请求中的字段按照名字匹配的原则,填入模型对象。:

  1. 新建的模型类需要与JSP里的界面文件进行名称匹配.

    1
    2
    3
    4
    5
    6
    public class Home {
    int id;
    String name;
    String title;
    String content;
    }
  2. 在views下新建一个index.jsp的View,通过EL表达式可以${home.title}来进行展示数据的绑定

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    <title>This is a Index Title</title>
    <link rel="stylesheet" type="text/css" href="../statics/css/index.css">

    </head>
    <body>
    <h2>Welcome to the fucking Spring world!</h2>
    <ui>
    <li>标题:${home.title}</li>
    <li>id:${home.id}</li>
    <li>正文:${home.content}</li>
    <li>名称:${home.name}</li>
    </ui>
    </body>
    </html>
  3. home变量即方式二里的map.put(“home”, home)或者方式三当中的使用HttpServletRequest的httpServletRequest.setAttribute(“home”, home);

  4. 其他: 如果要进行项目内的页面重定向,在返回的地方使用”redirect:” + 后面的地址;

文件上传

文件上传的概率其实相对来说比较简单,这里标记几个关键点。Demp用例上有单独的说明,使用MultipartFile来上传文件,表单需要加上enctype=”multipart/form-data”

1
2
3
4
<form method="post" action="/home/upload" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit"/>
</form>
1
2
3
4
5
6
7
8
9
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(@RequestParam("file") MultipartFile file) throws IOException{
if(!file.isEmpty()){
FileUtils.copyInputStreamToFile(file.getInputStream(), new File("/Users/Rocka/" + file.getOriginalFilename()));
return "success";
} else{
return "failed";
}
}

Spring与Json

一般步骤

  1. pom.xml引入maven依赖。一般引入最高版本,去maven远程库看最高版本号

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.7</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.7</version>
    </dependency>
    <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.7</version>
    </dependency>
  2. 配置dispacher-servlet.xml来处理接口返回的数据,主要是通过RequestMappingHandlerAdapter适配器来处理接口请求应该以什么返回等。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="messageConverters">
    <list>
    <!-- 设置返回字符串编码 -->
    <bean class="org.springframework.http.converter.StringHttpMessageConverter">
    <property name="supportedMediaTypes">
    <list>
    <value>text/html; charset=UTF-8</value>
    <value>application/json;charset=UTF-8</value>
    </list>
    </property>
    </bean>
    <!-- json转换器 -->
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    <property name="supportedMediaTypes">
    <list>
    <value>text/html; charset=UTF-8</value>
    <value>application/json;charset=UTF-8</value>
    </list>
    </property>
    </bean>
    </list>
    </property>
    </bean>
  1. 接口定义

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public @ResponseBody Home getHomeInJson(@PathVariable Integer id) {
    return homeService.getHomeById(id);
    }

    @RequestMapping(value = "/jsontype/{id}", method = RequestMethod.GET)
    public ResponseEntity<Home> getHomeInJson2(@PathVariable Integer id) {
    Home home = homeService.getHomeById(id);
    return new ResponseEntity<>(home, HttpStatus.OK);
    }

拦截器与过滤器

  • 作用场景

    • 解决编码乱码问题
    • 解决权限验证问题。
  • 过滤器

    过滤器的包在org.springframework.web.filter包中。具体的配置信息在web.xml当中,因为他的作用域在web服务器当中,所有请求都会经过过滤器进行操作。

    请求都经过utf8编码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-- 配置过滤器(设置为UTF-8) -->
    <filter>
    <filter-name>encoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>utf8</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>*</url-pattern>
    </filter-mapping>
  • 拦截器

    实现HandlerInterceptor接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class TestInterceptor implements HandlerInterceptor{

    //object handler表示被拦截请求的目标

    //返回true->请求被继续
    //返回false->请求被终止
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    return false;
    }


    //可以通过ModelAndView来改变显示的视图,或者修改发往视图的方法
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    // modelAndView.addObject("name","test");
    // modelAndView.setViewName("/success.jsp");
    }

    //可以做资源销毁等操作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
    }

    将拦截器注册进Spring MVC(dispatcher-servlet.xml)框架

    1
    2
    3
    <mvc:interceptors>
    <bean class="com.rocka.interceptor.TestInterceptor"></bean>
    </mvc:interceptors>
  • 拦截器的执行顺序为:preHandle() -> postHandle() -> afterCompletion()
  • 多个拦截器的执行顺序为:

    客户端request -> preHandle1() -> preHandle2() -> spring controller -> postHandle1() -> postHandle2() -> afterCompletion1() -> afterCompletion2() -> 客户端

  • 区别

    • 区别一过滤器Filter依赖于Servlet容器,基于回调函数,过滤范围大。
    • 拦截器Interceptor依赖于框架容器,基于反射机制,只过滤请求
  • 总结: 拦截器可以处理Web应用中请求的一些通用性问题,共性问题在拦截器处理,减少重复代码,利于维护

相关代码地址

GitHub点我

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器