现将 Spring MVC
中常用注解的使用整理如下.
@Controller
@Controller
注解可以标记一个类, 指明该类是一个控制器(Controller).
要想使 Spring
能够识别出使用 @Controller
标记的类使一个控制器, 还需要进行相应的配置, 有两种配置方式:
1、在 Spring MVC
的配置文件中定义一个 MyController(这是我们自定义的控制器,用@Controller标记)
的 bean
对象.
<bean class="com.tao.myapp.web.controller.MyController"/>
2、 在 Spring MVC
的配置文件中开启注解自动扫描, 让 Spring
自动的去指定的包下面扫描 @Controller
注解的类.
<context:component-scan base-package="com.tao.myapp.web.controller"/>
context:component-scan
默认扫描的注解类型是 @Component
, 不过, 在 @Component
语义基础上细化后的 @Repository
, @Service
和 @Controller
也同样可以被 context:component-scan
扫描识别.
@Component
这个注解是一个通用的注解, 表示 Spring
中的一个组件, 当我们不太清楚一个类要归到哪个层的组件中去的时候,可以使用这个注解, 不过通常 不建议使用
.
@Repository
这个注解用于 dao
层, 通常注解到 daoImpl
类上面.
@RequestMapping
这个注解是一个用来处理请求地址映射的注解, 可用于类或方法上. 用于类上, 表示类中的所有响应请求的方法都是以该地址作为父路径; 用于方法上, 表示特定而url请求将会被该方法处理.
@RequestMapping
的属性如下:
1、value
和 method
- value: 指定请求的
url
路径. 在使用的时候value
字段可以省略,url
用引号括起来.value
还支持通配符"*"
和"**"
.
@Controller
@RequestMapping("/myapp")
public class MyController {
/** 可以通过 http://localhost:8080/myapp/haha/test 访问 */
@RequestMapping("*/test")
public String test() {
System. out .println( "-----myapp test-----" );
return "test" ;
}
}
- method: 指定请求的
method
类型,GET
、POST
、PUT
、DELETE
等. 也可以通过@GetMapping
、@PostMapping
等注解替换.
@RequestMapping(value = "/testMethod" , method = {RequestMethod.GET, RequestMethod.DELETE})
public String testMethod() {
return "method";
}
2、consumes
和 produces
consumes: 指定请求的提交的内容的类型(
Content-Type
), 例如application/json
,text/html
.produces: 指定返回的内容类型, 仅当
request
请求头中的(Accept
)类型中包含该指定类型才返回.
3、 params
和 headers
- params: 指定
request
中必须包含某些参数值时, 才让该方法处理.
@RequestMapping(value = "/testParams", params = {"param1=value1", "param2", "!param3"})
public String testParams() {
System.out.println("-----------test Params-----------");
return "testParams";
}
如上例所示, params
属性指定了三个参数, 这些参数都是针对请求参数而言的, 它们分别表示参数 param1
的值必须等于 value1
; 参数 param2
必须存在, 值无所谓; 参数 param3
必须不存在. 只有当请求 /testParams
并且满足指定的三个参数条件的时候才能访问到该方法. 所以当请求 /testParams?param1=value1¶m2=value2
的时候能够正确访问到该 testParams()
方法, 当请求 /testParams?param1=value1¶m2=value2¶m3=value3
的时候就不能够正常的访问到该方法. 因为在 params
参数里面指定了参数 param3
是不能存在的.
- headers: 指定
request
中必须包含某些指定的header
值, 才能让该方法处理请求.
@RequestMapping(value = "/testHeaders" , headers = {"host=localhost" ,"Accept"})
public String testHeaders() {
return "headers";
}
headers
属性的用法和功能与 params
属性相似.
在上面的代码中当请求 /testHeaders
的时候, 只有当请求头包含 Accept
信息, 且请求的 host
为 localhost
的时候才能正确的访问到 testHeaders()
方法.
@Resource
和 @Autowired
@Resource
和 @Autowired
都是做 bean
的注入时使用.
@Resource
不是 Spring
的注解, 它的包是 javax.annotation.Resource
.
两者都可以写在字段和setter方法上. 两者如果都写在字段上, 那么就不需要再写setter方法.
1、 @Autowired
@Autowired
是 Spring
提供的注解, 所在的包为 org.springframework.beans.factory.annotation.Autowired
.
@Autowired
注解是按照类型( byType
) 装配依赖对象的, 默认情况下它要求依赖对象必须存在, 如果允许null值, 可以设置它的 required
属性为 false
. 如果我们想使用按照名称( byName
) 来装配, 可以结合 @Qualifier
注解一起使用.
2、 @Resource
@Resource
默认按照名称( byName
) 来自动注入. @Resource
有两个重要的属性: name
和 type
. Spring
将 @Resource
注解的 name
属性解析为 bean
的名字, 而 type
属性则解析为 bean
的类型. 所以, 如果使用 name
属性, 则使用 byName
的自动注入策略; 而使用 type
属性时则使用 byType
自动注入策略. 如果既不指定 name
也不指定 type
属性, 这时将通过反射机制使用 byName
自动注入策略.
最好是将
@Resource
放在setter
方法上, 因为这样更符合面向对象的思想, 通过set
、get
去操作属性, 而不是直接去操作属性.
@Resource
的作用相当于 @Autowired
, 只不过 @Autowired
默认是按照 byType
自动注入.
@PathVariable
这个注解用于将请求 url
中的模板变量映射到处理方法的参数上, 也就是说从请求的路径上取出需要的参数.
@Controller
public class TestController {
@RequestMapping(value = "/user/{userId}/roles/{roleId}", method = RequestMethod.GET)
public String getLogin(
@PathVariable("userId") String userId,
@PathVariable("roleId") String roleId) {
System.out.println("User Id : " + userId);
System.out.println("Role Id : " + roleId);
return "hello";
}
@RequestMapping(value = "/javabeat/{regexp1:[a-z-]+}", method = RequestMethod.GET)
public String getRegExp(@PathVariable("regexp1") String regexp1) {
System.out.println("URI Part 1 : " + regexp1);
return "hello";
}
}
@Controller
@RequestMapping("/test/{variable1}")
public class MyController {
@RequestMapping("/showView/{variable2}")
public ModelAndView showView(
@PathVariable("variable1") String variable1,
@PathVariable("variable2") int variable2) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("viewName");
modelAndView.addObject("需要放到 model 中的属性名称", "对应的属性值,它是一个对象");
return modelAndView;
}
}
@RequestHeader
这个注解可以将 Request
请求(HTTP请求
)中的 header
请求头部分的属性值绑定到处理方法的参数上.
Host localhost:8080
Accept text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Language fr,en-gb;q=0.7,en;q=0.3
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 300
@RequestMapping("/displayHeaderInfo")
public void displayHeaderInfo(
@RequestHeader("Accept-Encoding") String encoding,
@RequestHeader("Keep-Alive") long keepAlive) {
System.out.println("Accept-Encoding : " + encoding);
System.out.println("Keep-Alive : " + keepAlive);
}
上面的代码, 通过使用 @RequestHeader
把 header
部分的 Accept-Encoding
的值绑定到参数 encoding
上了; 把 Keep-Alive
的值绑定到参数 keepAlive
上了.
@CookieValue
这个注解可以将 Request
请求( HTTP请求
)的 header
头部信息中关于 Cookie
的值绑定到方法的参数上.
假设有如下
Cookie
值:
JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
@RequestMapping("/displayHeaderInfo")
public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie) {
System.out.println("Cookie : " + cookie);
}
@RequestParam
这个注解主要用于在 Spring MVC
后台控制层获取请求参数.
通常在
Controller
中获取请求参数有两种方法:
1. request.getParameter(“参数名”)
2. 使用@RequestParam
注解
@RequestParam
有三个常用参数:
value = “isApp”, required = false, defaultValue = “0”
value
: 参数名字, 即前端传入的请求中参数的名字.required
: 是否必须, 默认是true, 表示请求中一定要有相应的参数, 否则将报404错误码.defaultValue
: 参数的默认值, 表示如果请求中没有同名参数时的默认值, 默认值可以是SpEL表达式, 如“#{systemProperties['java.vm.version']}
”.
假设请求的url为
localhost:8080/myapp/test/?userName=zhangsan
@GetMapping("/requestParm")
public void getRequestParm(@RequestParam(value = "username", required = false, defaultValue = "admin") String username) {
System.out.println("username : " + username);
}
注意: 如果设置了
defaultValue
的值, 它将默认的设置required
的值为false
.
@RequestBody
这个注解用于将 Controller
的方法参数, 根据 HTTP Request Header
的 Content-Type
的内容, 通过适当的 HttpMessageConverter
转换为 Java
类.
当 POST
或者 PUT
的数据是 JSON
格式或者 XML
格式, 而不是普通的键值对形式的时候使用这个注解.
@RequestMapping(value = "/testRequestBody", method = RequestMethod.POST)
@ResponseBody
public Person testRequestBody(@RequestBody Person p) {
System.out.println("creating a person : " + p);
return p;
}
对应的前端 ajax
请求:
$.ajax({
url: "testRequestBody",
data: '{"name":"小红","age":12}', //要用双引号!!
contentType: "application/json;charset=utf-8", // 因为上面是json数据
type: "POST",
headers: {
// Accept: "application/xml",
Accept: "application/json",
},
success: function (data, textStatus) {
console.log(data);
alert(data);
},
error: function (data, textStatus, errorThrown) {
console.log(data);
},
});
@ResponseBody
该注解用于将 Controller
的方法返回的对象, 根据 HTTP Request Header
的 Accept
的内容, 通过适当的 HttpMessageConverter
转换为指定格式后, 写入到 Response
对象的 body
数据区.
当返回的数据不是 html
标签的页面, 而是其他某种格式的数据时( 如 json
、xml
等 )使用.
@ExceptionHandler
注解到方法上,出现异常时会执行该方法.
@ControllerAdvice
这个注解能够使一个 Contoller
成为全局的异常处理类, 类中用 @ExceptionHandler
注解的方法可以处理所有 Controller
发生的异常.
@ControllerAdvice
public class GlobalExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
@ExceptionHandler(BusinessException.class)
@ResponseBody
public ResponseMsg businessError(BusinessException exception) {
logger.info("Request raised a BusinessException, business code is {}", exception.getCode());
return new ResponseMsg(exception.getCode(), exception.getMessage());
}
@ExceptionHandler(Exception.class)
@ResponseBody
public ResponseMsg sysError(Exception exception) {
String msg = "出错了";
if(exception instanceof MaxUploadSizeExceededException) {
msg = "上传文件过大";
}
//exception.printStackTrace();
logger.error("Request raised " + exception.getClass().getSimpleName(), exception);
return new ResponseMsg(GeneralConst.SYS_ERROR, msg);
}
}
@InitBinder
使用 @InitBinder
来处理Date类型的参数.
//the parameter was converted in initBinder
@RequestMapping("/date")
public String date(Date date) {
System.out.println(date);
return "hello";
}
//At the time of initialization,convert the type "String" to type "date"
@InitBinder
public void initBinder(ServletRequestDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
参考:
https://blog.csdn.net/chenpeng19910926/article/details/70837756