SpringMVC注解
打卡:日常学习第二天
@Controller 控制器注解
@RequestMapping注解
1)@RequestMapping 注解为控制器指定某一个URL请求路径
2)@RequestMapping注解既可以写在类上也可以卸载方法上
a.在类上标注:第一级的访问目录
b.在方法上标注:第二级的访问目录
3)@RequestMapping中的常用属性
a. path 请求的路径
b. value 与path属性是一样的
c. params 限定请求参数的条件
d.method 指定该方法的请求方式
e.headers 发送过来的请求中必须要包含的请求头
f. consumes 指定处理请求的提交内容类型(Content-Type),如果http的请求头中的Content-Type与@ RequestMapping中规定的媒体类型一致,方法才能响应。
g. produces 指定返回值类型,则http请求的Accept必须与生成媒体类型一致才可以
4)@RequestMapping作用:
当DispatcherServlet 截获请求后,进行解析,通过控制器匹配@RequestMapping提供的映射信息确定请求所对应的处理方法。
案例演示
编写Controller控制器层的HelloDemo类
path、value、method 属性使用演示案例
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class HelloDemo {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(){
return "hello";
}
/**
* @RequestMapping("/hello") 映射路径
* @param username 相当于request.getParameter("name")
* @param model 用于存储数据,类似于request.setAttribute("name",name)
* @return
*/
@RequestMapping(path = "/hello",method = RequestMethod.POST)
public String sayHello(String username, String password,Model model){
model.addAttribute("msg",username+"---"+password);
return "hello";
}
}
编写hello.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>入门案例</title>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/hello.do">
<input type="text" name="username" id="username" placeholder="账号">
<input type="password" name="password" id="password" placeholder="密码">
<input type="submit" value="登录">
</form>
<h3>${msg}</h3>
</body>
</html>
params属性案例演示
@Controller
public class HelloDemo {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(){
return "hello";
}
/**
* @RequestMapping("/hello") 映射路径
* @param username 相当于request.getParameter("name")
* @param model 用于存储数据,类似于request.setAttribute("name",name)
* @return
*/
//params = {"username","password"} 表示请求过来的参数必须含有username、password这两个参数。否则报错
@RequestMapping(path = "/hello",method = RequestMethod.POST,params = {"username","password"})
public String sayHello(String username, String password,Model model){
model.addAttribute("msg",username+"---"+password);
return "hello";
}
}
consumes、product属性案例演示
import com.ts.entity.User;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.awt.*;
@Controller
public class HelloDemo {
@GetMapping("/hello")
public String hello(){
return "hello";
}
/**
* consumes属性:如果http的请求头中的Content-Type与@ RequestMapping中规定的consumes媒体类型一致,方法才能响应。
* 浏览器的用户异步登录,指明contentType :"application/json" , contentType默认值为"application/x-www-form-urlencoded :
*@RequestBody注解,指明方法参数与http的请求体数据绑定。
* @RequestBody用来接收前端传递给后端的json字符串,数据不是源于http的参数,而是源于http的请求体。
* 在映射方法指明生产媒体类型,则http请求的Accept必须与生成媒体类型一致才可以
* 在ajax中指定dataType:"json"后,http的请求头格式如: Accept: application/json, text/javascript
* 加上@ResponseBody注解后,会自动将返回结果在响应体中响应到客户端。User对象会自动转为json对象。但是需要加入jackson相关依赖才可。
* @param user 实体类
* @return
*/
@PostMapping(path = "/hello",consumes = {"application/json"},produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
public User sayHello(@RequestBody String user){
System.out.println(user);
User user1=new User();
user1.setUsername(user.split("&")[0].split("=")[1]);
user1.setPassword(user.split("&")[1].split("=")[1]);
return user1;
}
}
consumes、product中的 .jsp 页面ajax发送请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>入门案例</title>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.4.4.min.js"></script>
</head>
<script>
function login() {
var username = $("#username").val();
var password = $("#password").val();
var user={username:username,password:password};
$.ajax({
type:"POST",
url:"${pageContext.request.contextPath}/hello.do",
data:user,
dataType:"json",
contentType:"application/json",
success:function (user) {
alert(user.username+"输出传送的数据"+user.password);
},
error:function () {
alert("请求失败,出现异常");
}
})
}
</script>
<body>
<form method="post" action="${pageContext.request.contextPath}/hello.do">
<input type="text" name="username" id="username" placeholder="账号">
<input type="password" name="password" id="password" placeholder="密码">
<input type="button" onclick="login()" value="登录">
</form>
</body>
</html>
@RequestParam 注解
1)@RequestParam:绑定请求参数到控制器的方法参数
2)@RequestParam中的常用属性
a. value:请求参数中的参数名称
b. required:默认为 true, 表示请求参数中必须包含对应的参数,若不存在,将抛出异常
c. defaultValue: 默认值,当没有传递参数时使用该值
案例演示
控制器层类的编写,其jsp同上
@Controller
public class HelloDemo {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String hello(){
return "hello";
}
/**
* @RequestMapping("/hello") 映射路径
* @param username 相当于request.getParameter("name")
* @param model 用于存储数据,类似于request.setAttribute("name",name)
* @return
*/
/*
@RequestParam(value = "username",required = true;表示请求中的参数必须含有username参数名
@RequestParam(value = "password",required = false,defaultValue = "6666666")
required = false;表示password参数是可选的,如果请求过来的url中有这个参数,则使用真实的值
如果请求过来的url没有这个参数,defaultValue = "6666666"则使用默认值
*/
@RequestMapping(path = "/hello",method = RequestMethod.POST)
public String sayHello(@RequestParam(value = "username",required = true)String username,
@RequestParam(value = "password",required = false,defaultValue = "6666666") String password,
Model model){
model.addAttribute("msg",username+"---"+password);
return "hello";
}
}
@PathVariabl 注解
1)@PathVariable注解,可以创建RESTFul风格的web站点。
2)@PathVariable 解析使用URI模板
3)用于绑定 url 中的占位符。例如:请求 url 中 /hello/{username},这个{username}就是 url 占位符。
4)@PathVariable 中的常用属性
a. value:用于指定 url 中占位符名称。
b. required:表示是否必须提供占位符。
案例演示
控制层类的编写,jsp页面同理
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class HelloDemo {
/**
* @RequestMapping("/hello") 映射路径
* @param username 相当于request.getParameter("name")
* @param model 用于存储数据,类似于request.setAttribute("name",name)
* @return
*/
/*
@RequestMapping(path = "/hello/{username}&{password}",method = RequestMethod.GET)
请求方式为get请求,在url路径中必须包括username,password 参数,否则报错
在方法中参数中可以使用@PathVariable(value = "username",required = true;获取参数
*/
@RequestMapping(path = "/hello/{username}&{password}",method = RequestMethod.GET)
public String sayHello(@PathVariable(value = "username",required = true)String username,
@PathVariable(value = "password",required = false) String password,
Model model){
model.addAttribute("msg",username+"---"+password);
return "hello";
}
}
@GetMapping 与 @PostMapping 注解
Spring Framework 4.3之后,可以使用如下注解,简化@RequestMapping的写法:
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
使用以上五种注解的步骤
1、在spring-mvc.xml配置文件中 开启mvc注解驱动,导入mvc约束
2、编写控制层的类
案例演示
@Controller
public class HelloDemo {
@GetMapping("/hello")
public String hello(){
return "hello";
}
@PostMapping(path = "/hello")
public String sayHello(String username,String password,Model model){
model.addAttribute("msg",username+"---"+password);
return "hello";
}
}
HttpSession安全性
HttpSession的数据结构,是按照sessionid来操作数据的,没有线程的并发控制。
当高并发访问HttpSession对象时,可以设置 synchronizeOnSession = true
来提高线程安全性。
//将处理器放到spring容器中,才能生效
@Component
public class MyProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
return null;
}
//初始化之后执行的方法
//处理器适配器,中设置session是同步
public Object postProcessAfterInitialization(Object bean, String s) throws BeansException {
//判断当前对象是不是处理器适配器
if(bean instanceof RequestMappingHandlerAdapter){
//向下转型为适配器
RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;
//条用适配器特有的设置session同步的方法
adapter.setSynchronizeOnSession(true);
}
//返回
return bean;
}
}
@ResquestBody与消息转换器
1)@RequestBody注解,指明方法参数与http的请求体数据绑定。
2)@ResquestBody用于获取请求体内容。
直接使用得到是 key=value&key=value...结构的数据。
3)@ResquestBody 不适用get 请求方式。
4)@RequestBody中常用属性
a. required 是否必须有请求体。
默认值是:true。当取值为 true 时,get 请求会报错。
如果取值为 false,get 请求得到是 null。
转换http请求体到方法参数,需要使用HttpMessageConverter。消息转换器还负责把方法参数转换为http回应体(response body)
RequestMappingHandlerAdapter支持@RequestBody注解,使用如下默认消息转换器:
ByteArrayHttpMessageConverter:转换字节数组
StringHttpMessageConverter:转换字符串
FormHttpMessageConverter:转换表单数据到MultiValueMap<String, String>.
SourceHttpMessageConverter:与XML数据源之间数据转换
案例演示‘
如果设置@RequestBody(required = true),get 请求会报错。
@PostMapping(path = "/hello",consumes = {"application/json"},produces = {MediaType.APPLICATION_JSON_VALUE})
@ResponseBody
public User sayHello(@RequestBody(required = true) String user){
System.out.println(user);
User user1=new User();
user1.setUsername(user.split("&")[0].split("=")[1]);
user1.setPassword(user.split("&")[1].split("=")[1]);
return user1;
}
配置消息转换器
方法一:注解形式
<mvc:annotation-driven>
<!--消息转换器,设置string编码-->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" id="stringHttpMessageConverter">
<constructor-arg value="UTF-8"></constructor-arg>
<property name="writeAcceptCharset" value="false"></property>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" id="byteArrayHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter" id="jackson2CborHttpMessageConverter"></bean>
</mvc:message-converters>
</mvc:annotation-driven>
方法二:bead形式
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" id="requestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"></constructor-arg>
<property name="writeAcceptCharset" value="false"></property>
</bean>
</list>
</property>
</bean>
@ResponseBody 与 转换器
@ResponseBody注解用于方法,表明方法返回信息将直接写入http回应体。
方法上没有@ResponseBody注解,String返回值表示视图名字。@ResponseBody主要用于ajax数据回应或字节流数据回应等,不经过视图,数据直接返回客户端。
同@RequestBody 一样,@ResponseBody也是使用HttpMessageConverter把方法返回数据转换为http回应体。
代码同@RequestBody
如何解决返回体中的乱码问题???
在 web.xml中配置编码过滤器,似于JavaWeb阶段
<!--配置编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
如果返回的数据直接是json格式的数据,字符中含有中文,此时会出现乱码问题,解决如下,配置消息转换器
<mvc:annotation-driven>
<!-- 配置消息转换器,设置String的编码 -->
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
<property name="writeAcceptCharset" value="false"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
@RestController 注解
1)如果控制器,只服务于JSON、XML、多媒体数据等,是REST风格,则通常使用
@RestController注解。
2)@RestController = @ResponseBody + @Controller
案例演示
最初学习的:
@Controller
public class HelloAction {
@RequestMapping("/say")
@ResponseBody
public String say(){
return "say hello to SpringMVC";
}
}
可以用@RestController注解代替以上的代码
@RestController
public class HelloAction {
@RequestMapping("/say")
public String say(){
return "say hello to SpringMVC";
}
}
HttpEntity
HttpEntity表示http的request和resposne实体,它由消息头和消息体组成。
步骤一:在.jsp中发送ajax请求
$.ajax({
type: "POST",
url: targetUrl,
data: user,//传递的参数
dataType:"json",//前端可以接收服务器传过来的数据的类型,json
contentType: "application/json",
beforeSend: function(xhr){//请求发送之前执行函数,添加请求头
xhr.setRequestHeader("token","asdfghjk");
},
success: function(user){
alert(user.username);
},
error:function(){
alert("异常,请检查");
}
步骤二:在controller中获取请求头中的信息
@PostMapping(value = "/hello")
@ResponseBody
public ResponseEntity<User> login(@RequestBody String userString, RequestEntity requestEntity) {
System.out.println(requestEntity.getUrl());
//通过请求实体对象获取请求头,此处只演示几个,其余的自己获取即可
HttpHeaders requestHeaders = requestEntity.getHeaders();
System.out.println(requestHeaders);
//创建一个响应头
HttpHeaders responseHeader = new HttpHeaders();
responseHeader.set("myResponseHeader","myValue");
//userString绑定的请求体
//登录成功,拿到一个user对象
User user = new User();
user.setUsername(userString.split("&")[0].split("=")[1]);
user.setPassword(userString.split("&")[1].split("=")[1]);
//HttpStatus:响应的状态码
return new ResponseEntity<User>(user, responseHeader, HttpStatus.OK);
}
@ModelAttribute
1)它可以用于修饰方法和参数。
出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。
它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。
出现在参数上,获取指定的数据给参数赋值
案例演示
@Controller
@RequestMapping("/hello")
public class HelloDemo {
@ModelAttribute
public User add(){
User user=new User();
user.setUsername("rose");
user.setPassword("love");
return user;
}
@RequestMapping(path = "/login")
public String sayHello(){
return "hello";
}
}
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>入门案例</title>
</head>
<body>
<h1>${user.password}${user.username}</h1>
</body>
</html>
@SessionAttribute
1)@SessionAttribute 用于控制器方法间的参数共享
2)@SessionAttributes用于在会话中存储Model中指定名称的属性,用在类的级别。
3)@SessionAttribute注解用于方法参数,获取已经存储的session数据。
4)@SessionAttributes(value = {"user","shopcar"})
案例演示
@Controller
@RequestMapping("/account")
@SessionAttributes("account")//将model中的结果存入session
public class AccountAction {
@Autowired
private AccountService accountService;
//将account对象存入model
@ModelAttribute
public Account findAccout(String number){
return accountService.findAccount(number);
}
@RequestMapping("/find")
public String findAccount(String number){
return "account";
}
}
@Controller
@RequestMapping("/shopping")
public class ShoppingAction {
@RequestMapping("/buy")
public String buy(@SessionAttribute Account account){
//从session中获取account,消费
account.setBalance(account.getBalance()-500);
return "account";
}
}
@RequestMapping处理put、delete方法
Spring3.0 添加了一个过滤器,可以将这些请求转换为标准的 http 方法,使得支持 GET、POST、PUT 与 DELETE 请求。
案例演示
@Controller
public class HelloDemo {
@GetMapping("/hello")
public String a(){
return "hello";
}
@PutMapping(path = "/login")
@ResponseBody
public String sayHello(String username,String password){
System.out.println(username);
System.out.println(password);
return "put提交--成功";
}
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>入门案例</title>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/login.do">
<%-在首航设置隐藏域,name=”_method“ value="put/delete"--%>
<input type="hidden" name="_method" value="PUT">
<input type="text" name="username" id="username" placeholder="账号">
<input type="password" name="password" id="password" placeholder="密码">
<input type="submit" value="登录">
</form>
</body>
</html>
在web.xml配置隐藏过滤器
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@CookieValue
1)@CookieValue用于提取http请求中指定名称的cookie
2)@CookieValue 常用的属性
a. value:指定 cookie 的名称。
b. required:是否必须有此 cookie。
案例演示
@Controller
@RequestMapping("/user")
public class UserAction {
@GetMapping("/hello")
public String login(@CookieValue("JSESSIONID") String sessionID){
System.out.println("JSESSIONID :" + sessionID);
return "hello";
}
@PutMapping("/hello")
@ResponseBody
public String login(String username,String password,@CookieValue("JSESSIONID") String sessionID ){
System.out.println("JSESSIONID :" + sessionID);
System.out.println("put提交");
return "获取cookieValue成功";
}
}
@RequestHeader
1)@RequestHeader用于获取请求消息头。
2)@RequestHeader常用属性
value:指定消息头名称
required:是否必须有此消息头
案例演示
@GetMapping("/hello")
public String login(@RequestHeader("User-Agent")String userAgent,@RequestHeader
Map<String,String> headers){
System.out.println("User-Agent : "+userAgent);
//遍历map集合,获取所有的请求头的信息
for(Map.Entry<String,String> entry : headers.entrySet()){
System.out.println(entry.getKey());
}
return "hello";
}