文章目录
方法的参数
JavaEE组件
HttpServletRequest
HttpServletResponse
HttpSession
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import sun.management.Agent;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.Map;
/**
* @ClassName ParamController
* @Description TODO
* @Author Matthew
* @Date 2019/3/27 10:57
* @Version 1.0
**/
@Controller
@RequestMapping("/param")
public class ParamController {
@RequestMapping("/test1")
//按照我们之前所学返回值为void我们应该跳转到test1.jsp页面
//但我们接受HttpServletResponse那么spring就不会帮我们直接跳转到test1页面而是交给我们完成
public void test1(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
System.out.println("ParamController.test1," + request + " , " + response + " , " + session);
String username = request.getParameter("username");
session.setAttribute("username", username);
ServletContext application = session.getServletContext();
PrintWriter out = response.getWriter();
out.print("<h1>" + username + "</h1>");
out.flush();
out.close();
}
}
ParamController.test1,org.apache.catalina.connector.RequestFacade@1e02de28 , org.apache.catalina.connector.ResponseFacade@7c61acbd , org.apache.catalina.session.StandardSessionFacade@60ab2b0c
IO流
InputStream/OutputStream
Reader/Writer
@RequestMapping("/test2")
public void test2(InputStream inputStream, OutputStream outputStream) {
//相当于如下代码
//InputStream is = req.getInputStream();
//OutputStream os = req.getOutputStream();
System.out.println("ParamController.test2" + inputStream + " , " + outputStream);
}
@RequestMapping("/test3")
public void test3(Reader reader, Writer writer) {
// Reader reader = req.getReader();
// Writer writer = req.getWriter();
System.out.println("ParamController.test3" + reader + " , " + writer);
}
test2
ParamController.test2org.apache.catalina.connector.CoyoteInputStream@4b6eef19 , org.apache.catalina.connector.CoyoteOutputStream@3a6bfe52
test3
ParamController.test3org.apache.catalina.connector.CoyoteReader@48d05011 , org.apache.catalina.connector.CoyoteWriter@61ff6d57
向界面传递数据
Model、Map、ModelMap
将数据存储到Request作用域中
@RequestMapping("/test4")
public String test4(Model model, Map map, ModelMap modelMap) {
model.addAttribute("name", "tom");
map.put("age", 20);
modelMap.addAttribute("sex", "man");
modelMap.put("address", "beijing");
return "result";
}
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: Matthew
Date: 2019/3/27
Time: 11:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
name:${requestScope.name} <br>
age:${requestScope.age} <br>
sex:${requestScope.sex} <br>
address:${requestScope.address} <br>
</body>
</html>
String和基本类型
@RequestParam 表示参数来源于请求参数,默认所有参数都添加该注解,参数值来源于同名的请求
参数
@RequestMapping("/test5")
public String test5(@RequestParam(name = "name") String username, int age, @RequestParam(required = false, defaultValue = "180") Double height) {
System.out.println("ParamController.test5, username:" + username + " , age" + age + " , height" + height);
return "result";
}
ParamController.test5, username:alice , age12 , height180.0
@PathVariable 表示参数来源于URL
@RequestMapping("/test6/{id}")
public String test6(@PathVariable("id") int userid, String name) {
System.out.println("ParamController.test6, userid = " + userid + ", name = " + name);
return "result";
}
ParamController.test6, userid = 2, name = alice
@RequestHeader 表示参数来源于请求头
@RequestMapping("/test7")
public String test7(@RequestHeader("User-Agent") String userAgent,@RequestHeader("Cookie") String cookie){
System.out.println("ParamController.test7, userAgent = " + userAgent + ", Cookie = " + cookie);
return "result";
}
ParamController.test7, userAgent = Apache-HttpClient/4.5.6 (Java/1.8.0_152-release), Cookie = JSESSIONID=69E0EC8DC29DF51B2C35273C73579CFF
@CookieValue 表示参数来源于Cookie
@RequestMapping("/setCookie")
public String setCookie(HttpServletResponse response){
Cookie cookie = new Cookie("username", "admin");
cookie.setMaxAge(7*24*60*60);//7天
response.addCookie(cookie);
return "result";
}
@RequestMapping("/test8")
public String test8(@CookieValue("username") String username,@CookieValue("JSESSIONID") String sessionId){
System.out.println("ParamController.test5, username:" + username + ", sessionID = " + sessionId);
return "result";
}
限制性setCooike然后运行test8,username的值位admin
ParamController.test5, username:admin, sessionID = 94A072A8342F60219C68A85278F077FB
@RequestBody 表示参数来源于请求体(只有post请求才会有)
@RequestMapping("/test9")
public String test9( String requestBody) {
System.out.println("RequestBody = " + requestBody);
return "result";
}
RequestBody = username=qwe&password=qwe
自定义类型
@ModelAttribute 将请求数据转换为对象
条件:对象的属性名必须与表单元素的名称相同
@ModelAttribute注解有两种用法:
- 在方法参数的前面添加该注解
作用:将请求参数转换为对象
package vo;
import entity.Address;
import jdk.nashorn.internal.objects.annotations.Property;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.ModelAttribute;
import javax.validation.constraints.Pattern;
import java.io.InputStream;
/**
* @Description TODO
* @Author Matthew
* @Date 2019/3/28 20:27
* @Version 1.0
*/
public class UserVo {
private String username;
private String password;
private String phone;
private String email;
private Integer age;
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "UserVo{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", phone='" + phone + '\'' +
", email='" + email + '\'' +
", age=" + age +
", address=" + address +
'}';
}
}
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import vo.UserVo;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
/**
* @Description TODO
* @Author Matthew
* @Date 2019/3/28 20:24
* @Version 1.0
*/
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/regist")//ModelAttribute可加可不加
public String regist(@Valid UserVo userVo, Errors errors){
System.out.println(userVo);
return "success";
}
@ModelAttribute("types")
public List<String> getTypes(){
System.out.println("UserCOntroller.getTypes");
List<String> types = Arrays.asList("服装", "数码", "食品");
return types;
}
@RequestMapping("/test")
public String test(UserVo userVo){
return "result";
}
}
regist页面跳转regist
UserCOntroller.getTypes
UserVo{username=‘wqe’, password=‘12312’, phone=‘13111111111’, email=‘941076795@qq.com’, age=12, address=Address{city=‘辽宁’, province=‘沈阳’}}
- 在方法的上面添加该注解
作用:在调用所有目标方法前都会调用添加@ModelAttribute注解的方法,并向模型中添加数据
regist页面跳转test
UserController.getTypes
UserVo{username=‘wqe’, password=‘1233’, phone=‘13111111111’, email=‘941076795@qq.com’, age=12, address=Address{city=‘辽宁’, province=‘沈阳’}}
错误参数
Errors、BindingResult
用来接受错误信息,实现服务端的数据校验
实际开发中,既要做客户端表单校验,又要做服务端数据校验
@RequestMapping("/regist")//ModelAttribute可加可不加
public String regist(UserVo userVo, Errors errors){
//手动进行服务端数据校验
if(userVo.getAge() < 0 || userVo.getAge() >120){
errors.reject("年龄有误,年龄只能在0-120之间");//手动添加错误消息
}
//判断是否有错误
if (errors.hasErrors()) {
System.out.println(errors);//服务端校验的错误消息一般只在后台处理
return "step1";
}
System.out.println(userVo);
return "success";
}
UserController.getTypes
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Error in object ‘userVo’: codes [年龄有误,年龄只能在0-120之间.userVo,年龄有误,年龄只能在0-120之间]; arguments []; default message [null]
服务端数据校验
简介
JSR303校验
JSR303是一个数据验证的标准规范,用于对Java Bean中的属性进行校验,称为Bean Validation
提供了常用的校验注解
Hibernate Validator
是JSR303的一个参考实现,并提供了扩展注解
用法
添加jar包
<!-- hibernate-validator -->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
</dependencies>
为参数对象添加注解
public String regist(@Valid UserVo userVo, Errors errors){
为属性添加校验注解
@NotEmpty(message = "用户名不能为空")
@Pattern(regexp = "\\w{2,10}", message = "用户名只能包含数字、字母、下划线,且长度为6-10位")
private String username;
@Length(min = 4, max = 10, message = "密码必须位4-10位")
private String password;
@Pattern(regexp = "(139|133|131)\\d{8}", message = "手机号格式不正确")
private String phone;
@Email(message = "邮箱格式不正确")
private String email;
@Range(min = 1, max = 120, message = "年龄在1-120之间")
private Integer age;
@Property
private Address address;
类型转换
简介
数据绑定流程:获取值——>查找转换器——>转换——>后台校验——>数据绑定
两种解决方式:
方式1:使用PropertyEditor
方式2:使用Converter(推荐)
2. 使用PropertyEditor
步骤:
- 定义属性编辑器
- 注册属性编辑器
@InitBinder
注册属性编辑器
@InitBinder
public void initBinder(DataBinder binder) {
binder.registerCustomEditor(Address.class,new AddressEditor());
}
缺点:
代码嵌套在Controller层中只能从字符串转换
- 使用Converter
步骤:- 定义转换器,实现Converter接口
- 管理自定义转换器
<!--管理自定义转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="converter.String2AddressConverter"/>
<bean class="converter.Address2StringConverter"/>
</set>
</property>
</bean>
- 加载应用自定义管理器
将实体类Uservo中的实体类参数Address和字符串之间进行转换
package converter;
import entity.Address;
import org.springframework.core.convert.converter.Converter;
/**
* @Description TODO
* @Author Matthew
* @Date 2019/3/29 18:57
* @Version 1.0
*/
public class Address2StringConverter implements Converter<Address,String> {
@Override
public String convert(Address address) {
return "[" + address.getCity() + "-" + address.getProvince() + "]";
}
}
package converter;
import entity.Address;
import org.springframework.core.convert.converter.Converter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Description TODO
* @Author Matthew
* @Date 2019/3/29 18:50
* @Version 1.0
*/
public class String2AddressConverter implements Converter<String, Address> {
@Override
public Address convert(String source) {
Pattern pattern = Pattern.compile("\\[(.*)-(.*)\\]");
Matcher matcher = pattern.matcher(source);
if (matcher.matches()) {
String city = matcher.group(1);
String province = matcher.group(2);
Address address = new Address();
address.setCity(city);
address.setProvince(province);
return address;
} else {
throw new RuntimeException("地址转换失败");
}
}
}
@SessionAttributes
作用:将模型中指定名称的数据存储到session中
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttribute;
import org.springframework.web.bind.annotation.SessionAttributes;
import vo.UserVo;
import javax.servlet.http.HttpSession;
/**
* @Description TODO
* @Author Matthew
* @Date 2019/3/29 19:06
* @Version 1.0
*/
@Controller
@RequestMapping("/session")
@SessionAttributes("userVo")
public class SessionController {
@RequestMapping("/step1")
public String step1(){
return "step1";
}
@RequestMapping("/step2")
public String step2(UserVo userVo){
System.out.println("step2" + userVo);
return "step2";
}
@RequestMapping("/step3")
public String step3(UserVo userVo){
System.out.println("step3" + userVo);
return "step3";
}
@RequestMapping("/regist")
public String regist(UserVo userVo, HttpSession session){
System.out.println(session.getAttribute("userVo"));
System.out.println("regist" + userVo);
return "success";
}
}
step2UserVo{username=‘admin’, password=‘qwe’, phone=‘null’, email=‘null’, age=null, address=null}
step3UserVo{username=‘admin’, password=‘qwe’, phone=‘13111111111’, email=‘941076795@qq.com’, age=null, address=null}
UserVo{username=‘admin’, password=‘qwe’, phone=‘13111111111’, email=‘941076795@qq.com’, age=23, address=Address{city=‘辽宁’, province=‘沈阳’}}
registUserVo{username=‘admin’, password=‘qwe’, phone=‘13111111111’, email=‘941076795@qq.com’, age=23, address=Address{city=‘辽宁’, province=‘沈阳’}}
统一异常处理
- 简介
对异常进行统一处理
两种方式:
使用web技术提供的统一异常处理
使用SpringMVC提供的统一异常处理 - 使用web技术的异常处理
<!--404异常处理-->
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
<!--500异常-->
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
<body>
404 Page Not Found <br>
页面让狗狗叼走了。。。。。。
</body>
<body>
500 System Error<br>
系统出现问题,程序员正在修改中,请稍后再试。
</body>
- 使用SpringMVC的异常处理
步骤:
定义一个异常处理类(通知),添加@ControllerAdvice
定义异常处理方法,添加@ExceptionHandler
package controller;
import org.apache.ibatis.jdbc.Null;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
/**
* @Description TODO
* @Author Matthew
* @Date 2019/3/29 19:42
* @Version 1.0
*/
@ControllerAdvice
public class ExceptionAdvice {
@ExceptionHandler(ArithmeticException.class)
public String arithmetic(Exception e) {
System.out.println("警报,程序出现异常" + e.getMessage());
return "error/arithmetic";
}
@ExceptionHandler(NullPointerException.class)
public String nullpoint(Exception e) {
System.out.println("警报,程序出现空指针异常" + e.getMessage());
return "error/nullpoint";
}
@ExceptionHandler(Exception.class)
public String exception(Exception e) {
System.out.println("警报,程序出现异常" + e.getMessage());
return "error/exception";
}
}