目录
二、请求路径支持通配符(匹配各种不明确的请求路径),占位符(通过@PathVariable注解加在参数前取出请求路径)。
五、接收REST请求方式:即使用GET、POST、PUT、DELETE方式请求URL实现查、增、更、删操作
六、使用Serlvet的内置对象(直接在方法参数定义内置对象即可)
六、映射Cookie(Cookie是以键值对方式存储在客户端里的数据,使用@CookieValue("键名")加在方法参数前获取传来的Cookie)
七、映射基本类型请求参数( 使用@RequestParam("请求参数名")加在方法参数前映射请求参数)
八、映射Bean类型请求参数(直接在方法参数列表定义Bean即可)
十、将数据存入转发页面的session域(@SessionAttributes("Map里的键名或ModelAndView里的键名")注解加在类前)
十一、存入转发页面request域或session域前对数据的处理:使用@ModelAttribute直接加在方法前
十三、通过URL能直接访问WEB-INF里的JSP文件,让JSP页面能使用静态资源
十四、数据处理(form表单字段映射到Bean对象属性限制某个属性不绑定处理)
十五、数据映射(form表单的String字段映射到Bean对象的时间属性(Date)、基本类型包装属性(如:Float、Integer))
十六、数据约束(类似数据库约束来约束Bean类,使用Hibernate Validator来实现限制form表单的字段,不符合要求则报错。)
一、MVC的基本流程
https://blog.csdn.net/qq_38487155/article/details/89385100
补充:MVC的注解默认属性都是value
二、请求路径支持通配符(匹配各种不明确的请求路径),占位符(通过@PathVariable注解加在参数前取出请求路径)。
//@RequestMapping映射的请求URL支持通配符
/*
?:匹配文件名中的一个字符 –
*:匹配文件名中的任意字符 –
**: 匹配多层路径
*/
@RequestMapping("/**/testPath")
public String testPath() {
System.out.println("请求成功!");
return "success";
}
/*
* @RequestMapping映射的请求URL支持路径占位符,在方法参数列表里使用@PathVariable("占位id")取出路径占位参数
*/
@RequestMapping("/testPathVariable/{id}")
public String testPathVariable(@PathVariable("id") Integer id) {
System.out.println("请求成功:"+id);
return "success";
}
三、限制请求参数为什么或不为什么,违反则出异常。
//@RequestMapping的params:限制请求URL参数为什么,或不为为什么 headers:限制请求头为什么或不为什么
//以下表示请求参数username必须为admin、请求参数password不能为admin、不能有请求参数age
@RequestMapping(value="testPH",params= {"username=admin","password!=admin","!age"})
public String testPH() {
System.out.println("请求成功!");
return "success";
}
四、设置方法接收的请求方式
//@RequestMapping的value:设置请求URL,method:设置请求方式,method=RequestMethod.POST设置为post请求
@RequestMapping(value="/testPost",method=RequestMethod.POST)
public String testPost() {
System.out.println("Post方式!");
return "success";
}
五、接收REST请求方式:即使用GET、POST、PUT、DELETE方式请求URL实现查、增、更、删操作
1、在web.xml文件里添加HiddenHttpMethodFilter过滤器,将POST 请求转为DELETE或PUT 请求
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"
version="3.0">
<!-- 配置 org.springframework.web.filter.HiddenHttpMethodFilter: 用来将 POST 请求转为 DELETE 或 PUT 请求 -->
<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>
<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置DispatcherServlet的初始化参数,此处配置springXMl文件ID和文件路径 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 以下表示解析器文件路径在类路径下的springmvc文件 -->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<!-- 在这配置哪些请求可以给到Servlet -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2、在@RequestMapping注解里设置method属性,method=RequestMethod.DELETE
@RequestMapping(value="/testRest/{id}",method=RequestMethod.GET)
public String testRest(@PathVariable("id") Integer id) {
System.out.println("GET请求成功:"+id);
return "success";
}
@RequestMapping(value="/testRest",method=RequestMethod.POST)
public String testRest() {
System.out.println("POST请求成功!!");
return "success";
}
@RequestMapping(value="/testRest",method=RequestMethod.PUT)
public String testRestPUT() {
System.out.println("PUT请求成功!!");
return "success";
}
@RequestMapping(value="/testRest",method=RequestMethod.DELETE)
public String testRestDelete() {
System.out.println("DELETE请求成功!!");
return "success";
}
3、在发送POST请求里加入隐藏参数_method,值为 DELETE 或 PUT(即<form>的method属性仍设置为post,在<form>里包含隐藏参数 <input type="hidden" name="_method" value="PUT">)
<a href="HelloWorld/testRest/1">GET请求</a>
<br/>
<form action="HelloWorld/testRest" method="post">
<button>POST请求</button>
</form>
<form action="HelloWorld/testRest" method="post">
<button>PUT请求</button>
<input type="hidden" name="_method" value="PUT">
</form>
<form action="HelloWorld/testRest" method="post">
<button>DELETE请求</button>
<input type="hidden" name="_method" value="delete">
</form>
六、使用Serlvet的内置对象(直接在方法参数定义内置对象即可)
/*
* MVC可以使用Servlet的内置对象,只需要在方法参数里定义即可。
* 可使用的内置对象:HttpServletRequest
HttpServletResponse
HttpSession
java.security.Principal
Locale
InputStream
OutputStream
Reader
Writer
*/
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request,HttpServletResponse response,Reader reader) {
System.out.println(request+""+response);
System.out.println(reader);
return "success";
}
六、映射Cookie(Cookie是以键值对方式存储在客户端里的数据,使用@CookieValue("键名")加在方法参数前获取传来的Cookie)
/*
* 使用@CookieValue映射Cookie
* value:映射的Cookie键名
*/
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("data")String data) {
System.out.println(data);
return "success";
}
七、映射基本类型请求参数( 使用@RequestParam("请求参数名")加在方法参数前映射请求参数)
/*
* 使用@RequestParam映射请求参数
* value:映射的参数名
* required:是否必须包含该参数
* defaultValue:该参数时的默认值,在映射类型为基本类型(如int)非包装类型(Integer)时,该属性是必须的。
*/
@RequestMapping("/testRequestParams")
public String testRequestParams(@RequestParam("username")String username,@RequestParam(value="age",
required=false,defaultValue="0")int age) {
System.out.println(username+"、"+age);
return "success";
}
八、映射Bean类型请求参数(直接在方法参数列表定义Bean即可)
/*
* MVC会根据属性请求参数名自动匹配Bean对象属性名,并映射至方法参数。支持级联属性(即当前类包含其它类属性)
*/
@RequestMapping(value="/testBean",method=RequestMethod.POST)
public String testBean(User user) {
System.out.println(user);
return "success";
}
/*
* 测试不用@RequestParam会自动映射Get请求方式的Bean
*/
@RequestMapping(value="/testBeanGET")
public String testBeanGET(User user) {
System.out.println(user);
return "success";
}
九、将数据存入转发页面的request域(使用Map类直接加在参数列表,或者ModelAndView类加在参数列表的同时返回值需要是ModelAndView类型,原返回值传入ModelAndView的构造参数)
/*
* 使用ModelAndView类将数据存入转发页面request域,返回值需要设置成ModelAndView类型。同时将转发页面返回值
* 传入ModelAndView构造方法,ModelAndView提供了addObject方法(以键值对方式)来存入数据,方便在JSP页面使
* 用EL表达式取出
*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(ModelAndView modelAndView) {
modelAndView=new ModelAndView("success");
modelAndView.addObject("time",new Date());
return modelAndView;
}
/*
* 使用Map类将数据存入转发页面request域,使用Map无法获取网页传来的数据,即Map参数只起转发作用
* Map类不需要设置成返回值,只需要传入参数即可。
*/
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map) {
map.put("user", Arrays.asList("小米","小明","小红"));
return "success";
}
/*
* 使用Map作为参数无法获取用户请求传来的数据,只能用Bean作为参数获取,或者当参数列表里有Bean参数时,Map也会有参数
*/
@RequestMapping("/testMap2")
public String testMap2(Map<String,Object> map,User user) {
System.out.println(map.get("user"));
System.out.println(user);
return "success";
}
转发页面取出数据使用EL表达式: ${requestScope.time}、 ${requestScope.user}
十、将数据存入转发页面的session域(@SessionAttributes("Map里的键名或ModelAndView里的键名")注解加在类前)
@SessionAttributes(value= {"user1","user2"},types= {String.class,Integer.class})
@RequestMapping("/HelloWorld")
@Controller
public class HelloWorld {
...
}
/*
* 使用@SessionAttributes注解将数据存入Session域,@SessionAttributes注解加在处理请求类(@Controller类)前
* value:默认属性,通过属性名指定Map里的键名或者ModelAndView里的键名来确定哪些数据进入Session域
* type:通过类的class属性确定哪种类的所有对象进入Session域
*/
@RequestMapping("/testSession")
public String testSession(User user,Map<String,Object> map) {
map.put("user1", new User("A", "123", "139@qq.com", 12, new Address("广东","汕头")));
map.put("user2", new User("B", "456", "298@qq.com", 18, new Address("湖北","武汉")));
map.put("school", "武汉生物工程学院");
map.put("age", 21);
return "success";
}
十一、存入转发页面request域或session域前对数据的处理:使用@ModelAttribute直接加在方法前
/*
* 方法前@ModelAttribute作用:会在MVC将网页传来Bean对象封装数据前(即调用testModelAttribute方法前)执行,
* 可以防止Bean某个属性没有传值时使用数据库对象默认值,注意:当属性有值,数据
* 库对象属性也有值时保持数据库对象属性值优先。
* 运行流程:
* 1. 执行 @ModelAttribute 注解修饰的方法: 从数据库中取出对象, 把对象放入到了 Map 中. 键为: user(类名小写)
* 2. SpringMVC 从 Map 中取出 User 对象, 并把表单的请求参数赋给该 User 对象的对应属性.
* 3. SpringMVC 把上述对象传入目标方法的参数.
*
* 注意: 1、在 @ModelAttribute 修饰的方法中, 放入到 Map 时的键需要和请求方法入参类型的第一个字母小写的字符串一致!
* 不一致时请求方法只有参数为Bean时才能获取到@ModelAttribute 修饰的方法存入的数据,且需要在请求方法参数前
* 加@ModelAttribute(" @ModelAttribute 修饰的方法中Map存入的键名"),
* 不一致时转发页面获取存入Map的Bean对象时同样需要修改为${requestScope.Map键名}
* 2、在 @ModelAttribute 修饰的方法中, 如果参数为Bean类型且没有map参数时,无法将从数据库取出Bean对象存入request域,
* 会导致Bean属性没有传值时不会使用数据库对象属性值,即仍为空。所以此时需要添加一个map参数
* 总结:@ModelAttribute 修饰的方法一定要有map参数。
* 3、请求方法使用map作为参数和Bean对象作为参数都会自动传入request域。
* 4、@ModelAttribute 修饰的方法返回值设不设置都行,设置的话一般要与请求方法返回值一致。
*/
@ModelAttribute
public void getData(Map<String, Object> map) {
//模拟从数据库取出的数据Bean对象,并存入map
map.put("abc", new User("A", "123", "139@qq.com", 12, new Address("广东","汕头"))); //传入map相应的Bean对象,键为类名首字母小写
}
/*@ModelAttribute
public void getData2(User user,Map<String, Object> map) {
//模拟从数据库取出的数据Bean对象,并存入map
user= new User("A", "123", "139@qq.com", 12, new Address("广东","汕头"));
map.put("user",user);
}*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(Map<String, Object> map) {
System.out.println("修改:"+map.get("user"));
return "success";
}
@RequestMapping("/testModelAttribute2")
public String testModelAttribute2(@ModelAttribute("abc")User user) {
System.out.println("修改:"+user);
return "success";
}
十二、请求转发与重定向:跳至相应方法或页面
/*
* 请求转发和重定向:在返回值前添加使用forward:/或redirect:即可完成转发或重定向。
* 重定向与请求转发区别:
> 请求转发请求服务器一次,即当前请求转发至另一请求(地址url不变);重定向请求服务器俩次,即重新发送请求。
<> 需要地址栏发生变化,那么必须使用重定向!
<> 需要在下一个Servlet中获取request域中的数据,必须要使用转发。
<> 请求转发的第二次请求方法可以获取第一次请求用户发来的数据,重定向是用户分别俩次向服务器发起俩个独立请求,
即重定向的第二次请求方法无法获取第一次请求用户发来的数据。
除了在WEB-INF外面的index页面可以使用拼接URL,其它在WEB-INF页面无法通过URL直接访问,只能通过Handler中转
除非配置<mvc:view-controller>
重定向到页面:redirect:/<mvc:view-controller>的view-name属性值
重定向到Handler里的方法:redirect:/@RequestMapping类注解value值/@RequestMapping方法注解value值
注意:POST和DELETE请求方法的无法转发请求被<mvc:view-controller>配置的页面,重定向可能会导致request域
的数据丢失页面无法正常显示,此处推荐使用原有视图解析器(即返回页面文件名通过视图解析器解析为url地址)。
总结:尽量使用默认视图解析来返回页面,请求转发与重定向来跳转执行方法,优先使用重定向(转发在用户刷新页面时可能出现不一致操作)
*/
@RequestMapping("/testFR")
public String testFR() {
/*System.out.println("您已转发");
return "forward:/index.jsp";*/
System.out.println("您已重定向");
//return "redirect:/index.jsp";
//return "redirect:/views/success";
return "redirect:/HelloWorld/testView";
}
十三、通过URL能直接访问WEB-INF里的JSP文件,让JSP页面能使用静态资源
<!-- 配置<mvc:view-controller>作用:WEB_INF里的JSP文件无法直接通过URL访问,配置使得可以直接通过url访问页面,
会导致不执行handler方法(即当前handler方法的数据处理和页面转发会失效),
若想让handler方法继续执行:配置<mvc:annotation-driven>
path:设置转发页面的访问路径,不能带文件后缀,以WEB_INF为初始路径
view-name:设置转发页面的文件名,需要与路径最后文件名一致
注意:该页面(此处配置的是views/success页面)无法被POST和DELETE方法的返回值使用请求转发访问,重定向可能会导致request域
的数据丢失页面无法正常显示,此处推荐使用原有视图解析器(即返回页面文件名通过视图解析器解析为url地址)转发/重定向
到相应的方法。
-->
<mvc:view-controller path="views/success" view-name="success"/>
<!-- 在实际开发中通常都需配置 mvc:annotation-driven 标签让handler方法继续执行
俩种使用情况:
1、直接访问JSP文件资源时需要调用请求方法使用,默认<mvc:view-controller>会跳过@RequestMapping注解方法
2、使用静态资源时需要调用请求方法使用,默认<mvc:default-servlet-handler/>会跳过@RequestMapping注解方法
-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--静态资源指:WebContent下的文件,不包括WEB-INF下的文件。如scripts文件
配置允许访问静态资源的标签: 将在 SpringMVC 上下文中定义一个DefaultServletHttpRequestHandler,
它会对进入 DispatcherServlet 的请求进行筛查, 如果发现是没有经过映射的请求(即不进入Handler方法的请求), 就将该请求交由
WEB 应用服务器默认的Servlet 处理. 如果不是静态资源的请求,才由 DispatcherServlet 继续处理
一般 WEB 应用服务器默认的 Servlet 的名称都是 default.
若所使用的 WEB 服务器的默认 Servlet 名称不是 default,则需要通过 default-servlet-name 属性显式指定 -->
<mvc:default-servlet-handler/>
十四、数据处理(form表单字段映射到Bean对象属性限制某个属性不绑定处理)
/* 数据绑定限制(form表单字段映射到Bean对象属性的绑定处理)
* 1、方法前添加@InitBinder注解,表明这是一个设置绑定方法
* 2、方法参数列表添加WebDataBinder对象,WebDataBinder用来完成表单字段映射到Bean对象属性
*/
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("lastName"); //设置不绑定lastName属性
}
十五、数据映射(form表单的String字段映射到Bean对象的时间属性(Date)、基本类型包装属性(如:Float、Integer))
/ * 注意:如果类型不一致(如int映射到Float,float映射到Integer),将使得Employee与form表单对象无法一一对应,会发生错误同时如果不满足 @DateTimeFormat注解和@NumberFormat注解的格式,也会报错
1、在springmvc文件里添加<mvc:annotation-driven></mvc:annotation-driven>
2、在Bean类的属性前添加相应的注解
@DateTimeFormat:可对java.util.Date、java.util.Calendar、java.long.Long 时间类型进行注解:
pattern 属性:自定义时间类型格式 –如:"yyyy-MM-dd hh:mm:ss"
iso 属性:系统给定的时间类型格式,包括四种:
ISO.NONE:默认值、不需要设置时间输入项
ISO.DATE :yyyy-MM-dd
ISO.TIME:hh:mm:ss.SSSZ
ISO.DATE_TIME:yyyy-MM-dd hh:mm:ss.SSSZ
@NumberFormat:可对类似数字类型的属性进行注解,它拥有两个互斥的属性:
pattern 属性:定义样式(String值),如patter="#,###";#代表位数,只要位数符合即可
style:类型为 NumberFormat.Style。用于指定– 样式类型,包括三种:Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、 Style.PERCENT(百分数类型)
*/
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern="#,###,###.#")
private Float salary;
十六、数据约束(类似数据库约束来约束Bean类,使用Hibernate Validator来实现限制form表单的字段,不符合要求则报错。)
1、加入 hibernate validator 验证框架的 jar 包:
hibernate-validator-5.0.0.CR2.jar
hibernate-validator-annotation-processor-5.0.0.CR2.jar
classmate-0.8.0.jar
jboss-logging-3.1.1.GA.jar
validation-api-1.1.0.CR1.jar
2、在springmvc文件里添加<mvc:annotation-driven></mvc:annotation-driven>
3、在Bean类的属性前添加验证限制
@Null:该属性必须为空
@NotNull:该属性不能为空
@Email:该属性必须为邮箱格式
@AssertTrue:该属性必须为true
@AssertFalse:该属性必须为false
@Min(value):该属性必须为数字,且不小于value
@Max(value):该属性必须为数字,且不大于value
@Size(max,min):该属性必须为数字,且在指定范围
@Past:该属性必须为一个过去的日期
@Future:该属性必须为一个未来的日期
@Pattern(表达式):该属性必须符合正则表达式
@Length:该属性字符串大小需要在指定范围内
@Range:该属性需要在合适范围内
4、在请求方法的Bean参数前加上 @Valid 注解
@RequestMapping(value="emp",method=RequestMethod.POST)
public String save(@Valid Employee employee,Map<String, Object>map) {
employeeDao.save(employee);
System.out.println("添加成功!"+employee);
/*map.put("employees", employeeDao.getAll());
return "redirect:/views/list";*/ //使用重定向到页面会导致重新发起第二次请求,该请求的request域没有任何Employee
return "redirect:/emps"; //使用重定向到方法,该方法返回值使用的是视图解析器(不是转发或重定向),request域中仍有数据。
/*map.put("employees", employeeDao.getAll());
return "forward:/views/list"; */ //使用转发原因:因为有使用同一request域,否则看不出增加了一个Employee效果
}
@NotEmpty
private String lastName;
@Email
private String email;
//1 male, 0 female
private Integer gender;
private Department department;
@Past
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
@NumberFormat(pattern="#,###,###.#")
private Float salary;
十七、以JSON格式将Bean对象传送至网页
/*
* 以JSON格式将Bean对象传送至网页
* 1、加入jar包:jackson-annotations-2.1.5.jar、jackson-core-2.1.5.jar、jackson-databind-2.1.5.jar
* 2、在方法前加@ResponseBody注解:该注解会将方法返回值通过适当的HttpMessageConverter
* 转换为指定格式后,写入到Response对象的body数据区,即返回值会直接作为数据传至网页
* 附加知识->在方法参数前加@RequestBody注解:获取网页请求体(请求参数),包含请求头等。
*/
@ResponseBody
@RequestMapping("getEmployees")
public Collection<Employee> getEmployees(){
return employeeDao.getAll();
}
@ResponseBody
@RequestMapping(value="testRequestBody",method=RequestMethod.POST)
public String testRequestBody(@RequestBody byte[] bytes) {
System.out.println(new String(bytes));
IOFile.getFile(bytes, "D:/", "myFile.txt");
return "Return Time:"+new Date();
}