java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringMVC中的常用注解

SpringMVC中的常用注解源码及解析

作者:空无多有

这篇文章主要介绍了SpringMVC中的常用注解源码及解析,SpringMVC是一种基于Java的Web框架,它使用了许多注解来简化开发过程,本文列举了一些常用的注解,需要的朋友可以参考下

用于配置控制器的注解

@Controller

该注解用用于修饰表现层控制器的注解

源码

@Target({ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME)
@Documented 
@Component public @interface Controller {
	// 用于指定存入IOC容器是Bean的唯一标识
	@AliasFor(annotation = Component.class) 
    String value() default "";
}

@RestController

该注解具备@Controller注解的全部功能,同时多了一个@ResponseBody注解的功能

源码

@Target(ElementType.TYPE) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Controller 
@ResponseBody public @interface RestController {
	// 用于指定存入ioc容器时bean的唯一标识。 @since 4.0.1 
	@AliasFor(annotation = Controller.class) 
	String value() default "";
}

用于提供方法映射的注解

@RequestMapping

该注解用于建立请求URL和处理请求方法之间的对应关系

注解在类上: 请求URL的第一级访问目录. 如果没有的话, 就相当于从应用根目录开始. 放在类上的目的就是为了将URL可以按照模块化管理.

源码以及解析

package org.springframework.web.bind.annotation;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    // 给当前url 提供一个名称
    String name() default "";
	// value: 用于指定请求的URL . 和path属性作用一样
	// 注意: 该属性的值 前边加不加 "/" 都是一样的.
    @AliasFor("path")
    String[] value() default {};
	// 4.2 版本中加入的注解 和value属性一样
    // @since 4.2
    @AliasFor("value")
    String[] path() default {};
	// method:用于指定请求的方式。它支持以下这些类型: 
    // GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
    // 是通过RequestMethod枚举指定的
    RequestMethod[] method() default {};
    // params:用于指定限制请求参数的条件。它支持简单的表达式。
    // 要求请求参数的key和value必须和配置的一模一样。
    // 示例: params = {"accountName"},表示请求参数必须有accountName
	//      params = {"moeny!100"},表示请求参数中money不能是100。
    String[] params() default {};
	// headers:用于指定限制请求消息头的条件。
    // 示例: RequestMapping(value = "/something", headers = "content-type=text/*")
    String[] headers() default {};
	// consumes:用于指定可以接收的请求正文类型(MIME类型)
    // 示例: consumes = "text/plain"  , consumes = {"text/plain", "application/*"}
    String[] consumes() default {};
	// produces:用于指定可以生成的响应正文类型。(MIME类型)
    // produces = "text/plain"
    // produces = {"text/plain", "application/*"}
    // produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    String[] produces() default {};
}

@GetMapping 、@PostMapping、 @PutMapping 、@DeleteMapping 、是@RequestMapping 注解的衍生注解

除了method指定以外 , 其他和@RequestMapping 相同

可以看下源码@PostMapping示例

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
    method = {RequestMethod.POST}
)
public @interface PostMapping {

增强控制器方法的注解

@ModelAttribute

它可以用于修饰方法,或者是参数。

@Controller
public class ModelAttributeController {
    @ModelAttribute("username")
    public String showModel(String username){
        System.out.println("showModel method name is "+username);
        username = username + "aaa";
        return username;
    }
    @RequestMapping("/useModelAttribute")
    public String useModelAttribute(@ModelAttribute("username") String username){
        System.out.println("controller method name is "+username);
        return "success";
    }
}

测试结果

showModel method name is test
controller method name is testaaa
success.jsp执行了

@ExceptionHandler

用于注释方法,表明当前方法是控制器执行产生异常后的处理方法.

示例:

自定义异常

package com.exception;
/**
 * 自定义异常(处理业务异常)
 */
public class CustomerException extends Exception{
    private String message;
    public CustomerException(String message){
        this.message = message;
    }
    @Override
    public String getMessage() {
        return message;
    }
}

异常后处理类

@ControllerAdvice
public class ExceptionHandlerAdvice {
    @ExceptionHandler(Exception.class)
    public String handleException(Model model, Exception e){
        String errorMsg = "";
        //判断Exception的类型是不是CustomerException
        if(e instanceof CustomerException){
            errorMsg = e.getMessage();
        }else {
            //系统异常
            errorMsg = "服务器内部错误,请联系管理员!";
        }
        model.addAttribute("errorMsg",errorMsg);
        return "error";
    }
}

接口控制器类

package com.web.controller;
@ControllerAdvice
public class ExceptionHandlerAdvice {
    @ExceptionHandler(Exception.class)
    public String handleException(Model model, Exception e){
        String errorMsg = "";
        //判断Exception的类型是不是CustomerException
        if(e instanceof CustomerException){
            errorMsg = e.getMessage();
        }else {
            //系统异常
            errorMsg = "服务器内部错误,请联系管理员!";
        }
        model.addAttribute("errorMsg",errorMsg);
        return "error";
    }
}

测试

<%-- ExceptionHandler注解的使用--%>
<a href="useExceptionHandler?age=111" rel="external nofollow" >ExcpetionHandler注解的使用</a>
<hr/>

@InitBinder

用于初始化表单请求参数的数据绑定器。

给控制器方法提供通知的注解

@ControllerAdive

用于给控制器提供一个增强的通知。

@RestControllerAdive

它和@ControllerAdvice注解的作用一样,并且支持@ResponseBody的功能

用于绑定控制器方法参数的注解

@RequestParam

此注解是从请求正文中获取请求参数,给控制器方法形参赋值的 当请求参数的名称和控制器方法形参变量名称一致时,无须使用此注解。 当没有获取到请求参数时,此注解还可以给控制器方法形参提供默认值。 只能用在方法的参数上.

示例:

 @RequestMapping("/useRequestParam")
 public String useRequestParam(@RequestParam(value = "page",defaultValue = "10") int page){
     System.out.println("当前页是:"+page);
     return "success";
 }

@RequestBody

该注解用于读取 Request 请求的 body 部分数据,使用系统默认配置的 HttpMessageConverter 进行解析,然后把相应的数据绑定到要返回的对象上; 再把 HttpMessageConverter 返回的对象数据绑定到 controller 中方法的参数上。

也就是说,如果是 json 格式的数据,我们要传入的参数是一个对象,那就必须使用 @RequestBody

示例:

@RequestMapping("/useRequestBody")
public String useRequestBody(@RequestBody(required = false) User user){
    //System.out.println("不支持跨域 user is "+user);
    System.out.println(" user is "+user);
    return "success";
}

 测试页面

    
    <a href="#" rel="external nofollow"  id="useRequestBodyAjax">RequestBody注解的使用</a>
    <%-- RequestBody注解的使用--%>
    <script src="js/jquery-2.2.3.min.js"></script>
<%--    <script src="${pageContext.request.contextPath}/js/jquery-2.2.3.min.js"></script>--%>
    <script type="text/javascript">
        //页面加载事件
        $(function () {
            //给Id为useRequestBodyAjax超链接绑定一个点击事件
            $("#useRequestBodyAjax").click(function () {
                alert("点击事件绑定成功");
                $.ajax({
                    url: "useRequestBody",
                    type: "post",
                    // data:"username=test&age=18&gender=male",
                    data: '{"username":"test","age":25,"gender":"male"}',//json
                    contentType: "application/json",
                    dataType: "text",
                    success: function (data) {
                        alert(data);
                    }
                });
            });
        })
    </script>

@RequestHeader

该注解是从请求消息头中获取消息头的值,并把值赋给控制器方法形参。

注意: 它只能出现在方法的参数上

    @RequestMapping("/useRequestHeader")
    public String useRequestHeader
        (@RequestHeader(value = "Accept-Language",required = false,defaultValue = "test") String header)
    {
        System.out.println("Accept-Language:"+header);
        return "success";
    }

@CookieValue

从请求消息头中获取Cookie的值,并把值赋给控制器方法形参。

属性:

@CookieValue(value = "JSESSIONID" , required = true,  defaultValue = "")

示例:

    @RequestMapping("/useCookieValue")
    public String useCookieValue(@CookieValue("JSESSIONID") String jsessionid){
        System.out.println(jsessionid);
        return "success";
    }

在这里插入图片描述

@PathVariable

restful 该注解是springmvc框架支持rest风格url的标识。用于获取请求url映射中占位符对应的值。

示例

@RequestMapping(method = RequestMethod.PUT,value = "/{id}")
public String update(@PathVariable Integer id, User user){
        //1.给user的id赋值
        user.setId(id);
        //2.输出
        System.out.println("user is "+user);
        return "success";
 }

改变响应方式的注解

@SessionAttributes

package com.web.controller;
/**
 * SessionAttribute和SessionAttributes注解的使用
 */
@Controller
@SessionAttributes(value = {"message"})
public class SessionAttributesController {
    /**
     * 往session域中存入数据
     * 在没有SessionAttributes注解时,当控制器方法的参数有Model,ModelMap时是默认往请求域中存入数据
     * @return
     */
    @RequestMapping("/useSessionAttributes")
    public String useSessionAttributes(Model model){
        model.addAttribute("message","存入请求域的数据");
        return "success";
    }
    @RequestMapping("/useSessionAttribute")
    public String useSessionAttribute(HttpServletRequest request,@SessionAttribute(value = "message",required = false) String message){
        System.out.println(message);
        System.out.println("request attribute "+request.getAttribute("message"));
        return "success";
    }
}

 @SessionAttributes 往会话域中存数据
 @SessionAttribute  从会话域中取数据

@ResponeBody

用于用流输出响应正文

将方法的返回值,以特定的格式写入到response的body区域,进而将数据返回给客户端。

@RequestMapping("/useResponseBody")
public String useResponseBody(){
        return "use response body";
}

提供跨域访问

@CrossOrigin

跨域访问

当一个域名请求另一个域名的资源时, 就是跨域 (协议,主机名, 端口任何一个不相同就是跨域)

域名模拟 C:/Windows/System32/drivers/ect/hosts(文件)
修改该文件,建立Ip和域名的对应关系
如何刷新域名不重启计算机
cmd命令行输入:
ipconfig /displaydns
ipconfig /flushdns

跨域请求中,请求时可以正常发出去,并且服务端也可以收到. 问题出在了响应身上,通过修改服务端的响应头就可以解决跨域问题.

解决跨域问题,不使用@CrossOrigin注解的解决办法-添加跨域过滤器

package com.filters;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CrossOriginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        try{
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse)res;
            System.out.println("解决跨域问题的过滤器执行了");
            //设置response的响应消息头实现跨域问题的解决
            /* 允许跨域的主机地址 */
            response.setHeader("Access-Control-Allow-Origin", "*");
            /* 允许跨域的请求方法GET, POST, HEAD 等 */
            response.setHeader("Access-Control-Allow-Methods", "*");
            /* 重新预检验跨域的缓存时间 (s) */
            response.setHeader("Access-Control-Max-Age", "3600");
            /* 允许跨域的请求头 */
            response.setHeader("Access-Control-Allow-Headers", "*");
            /* 是否携带cookie */
            response.setHeader("Access-Control-Allow-Credentials", "true");
            //放行
            chain.doFilter(request,response);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @Override
    public void destroy() {  }
}

在spring中提供了@CrossOrigin注解来解决跨域问题,

该注解可以放在类上和方法上, 以解决跨域问题.

    /**
     * 跨域访问的方法
     * @param user
     * @return
     */
    @RequestMapping("/useCrossOrigin")
    @ResponseBody
    @CrossOrigin
    public String useCrossOrigin(@RequestBody(required = false) User user){
        System.out.println("user is "+user);
        return "success";
    }

写在类上表示该类中的所有资源都允许跨域访问, 写在方法上表示仅该方法允许跨域访问.

注意: 一些静态资源 例如 img 中的 src , link 中的 href 中的是可以进行跨域访问的

比如在 一个jsp页面中 , 如果使用 response.sendRedirect(); 会有跨域问题, 改为 window.location.href = ‘//xxx.xxx.xxx’ 则不会有跨域问题 . (踏平的坑!)

到此这篇关于SpringMVC中的常用注解源码及解析的文章就介绍到这了,更多相关SpringMVC中的常用注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文