该注解用用于修饰表现层控制器的注解
源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component public @interface Controller {
// 用于指定存入IOC容器是Bean的唯一标识
@AliasFor(annotation = Component.class)
String value() default "";
}
该注解具备@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 "";
}
该注解用于建立请求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 {};
}
是@RequestMapping 注解的衍生注解 (除了method指定以外 , 其他和@RequestMapping 相同)
可以看下源码@PostMapping示例
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
method = {RequestMethod.POST}
)
public @interface PostMapping {
它可以用于修饰方法,或者是参数。
当修饰方法时,表示执行控制器方法之前,被此注解修饰的方法都会执行。
当修饰参数时,用于获取指定的数据给参数赋值。
@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执行了
用于注释方法,表明当前方法是控制器执行产生异常后的处理方法.
示例:
自定义异常
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">ExcpetionHandler注解的使用</a>
<hr/>
用于初始化表单请求参数的数据绑定器。
用于给控制器提供一个增强的通知。
它和@ControllerAdvice注解的作用一样,并且支持@ResponseBody的功能
此注解是从请求正文中获取请求参数,给控制器方法形参赋值的
当请求参数的名称和控制器方法形参变量名称一致时,无须使用此注解。
当没有获取到请求参数时,此注解还可以给控制器方法形参提供默认值。
只能用在方法的参数上.
示例:
@RequestMapping("/useRequestParam")
public String useRequestParam(@RequestParam(value = "page",defaultValue = "10") int page){
System.out.println("当前页是:"+page);
return "success";
}
该注解用于读取 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";
}
<br/>
<a href="#" id="useRequestBodyAjax">RequestBody注解的使用</a>
<br/>
<%-- 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>
<br/>
该注解是从请求消息头中获取消息头的值,并把值赋给控制器方法形参。
注意: 它只能出现在方法的参数上
@RequestMapping("/useRequestHeader")
public String useRequestHeader
(@RequestHeader(value = "Accept-Language",required = false,defaultValue = "test") String header)
{
System.out.println("Accept-Language:"+header);
return "success";
}
从请求消息头中获取Cookie的值,并把值赋给控制器方法形参。
属性:
@CookieValue(value = "JSESSIONID" , required = true, defaultValue = "")
示例:
@RequestMapping("/useCookieValue")
public String useCookieValue(@CookieValue("JSESSIONID") String jsessionid){
System.out.println(jsessionid);
return "success";
}
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";
}
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 从会话域中取数据
用于用流输出响应正文
将方法的返回值,以特定的格式写入到response的body区域,进而将数据返回给客户端。
@RequestMapping("/useResponseBody")
public String useResponseBody(){
return "use response body";
}
跨域访问
当一个域名请求另一个域名的资源时, 就是跨域
(协议,主机名, 端口任何一个不相同就是跨域)
跨域请求中,请求时可以正常发出去,并且服务端也可以收到.
问题出在了响应身上,通过修改服务端的响应头就可以解决跨域问题.
解决跨域问题,不使用@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 = ‘http://xxx.xxx.xxx’ 则不会有跨域问题 . (踏平的坑!)
因篇幅问题不能全部显示,请点此查看更多更全内容