Spring MVC
- 官网文档 https://docs.spring.io/spring-framework/docs/4.2.4.RELEASE/spring-framework-reference/html/mvc.html
回顾Servlt
-
新建Maven工程,导入pom依赖
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> </dependencies>
-
Servlet层
public class HelloServlet extends HttpServlet { //实现Servlet接口 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取参数,获取页面网站返回得method变量中的参数 String method=req.getParameter("method"); if(method.equals("add")){ //将参数变量msg返回 req.getSession().setAttribute("msg","执行了add方法"); } if(method.equals("del")){ req.getSession().setAttribute("msg","执行了del方法"); } //业务逻辑 //视图跳转 req.getRequestDispatcher("WEB-INF/jsp/hello.jsp").forward(req,resp); } @Override protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPut(req, resp); } }
-
web.xml配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <!-- 注册HelloServlet --> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.peggy.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <!--请求响应的user--> <servlet-name>HelloServlet</servlet-name> <url-pattern>/user</url-pattern> </servlet-mapping> </web-app>
-
静态资源
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> ${msg} </body> </html>
- localhost:8080/user?method=add
- localhost:8080/user?method=delete
Spring MVC
配置版
-
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--关联一个Spring的配置文件:【servlet-name】-servlet.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc-servlet.xml</param-value> </init-param> <!--启动级别 -1 --> <load-on-startup>1</load-on-startup> </servlet> <!--/ 匹配所有的请求;(不包括.jsp)--> <!--/* 匹配所有的请求;(包括.jsp)--> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
SpringMVC 的 配置文件 springmvc-servlet 官方名
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
<context:component-scan base-package="com.peggy.controller"/>
<!--让Spring MVC不处理静态资源-->
<mvc:default-servlet-handler/>
<!--
支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效
必须向上下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter实例
这两个实例分别在类级别和方法级别处理。
而annotation-driven配置帮助我们自动完成上述两个实例的注入。
-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="WEB-INF/jsp/"/>
<!--后端-->
<property name="suffix" value=".jsp"/>
</bean>
<bean name="/t1" class="com.peggy.controller.ControllerTest"/>
</beans>
- 操作业务Controller
- @Controller注解类型用于声明Spring类的实例是一个控制器(在讲IOC时还提到了另外3个注
解);
public class ControllerTest implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//返回一个视图对象 ModelAndView模型和视图
ModelAndView modelAndView = new ModelAndView();
//封装对象,放在ModelAndView中
modelAndView.addObject("msg","<h1>ControllerTest<h1>");
//封装要跳转的视图,放在ModelAndView中
modelAndView.setViewName("hello"); // 跳转访问的地址:WEB-INF/jsp/hello.jsp
return modelAndView;
}
}
- 将自己的类交给SpringIOC容器,注册bean
<!--将自己的类交给SpringIOC容器,注册Bean-->
<bean name="/t1" class="com.peggy.controller.ControllerTest"/>
- 跳转的jsp hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
- http://localhost:8080/hello
注解版
-
编写一个HelloController类
@Controller public class HelloController { //真实访问的地址: 项目名/HelloController/Hello @RequestMapping("/hello") public String sqyHello(Model model){ model.addAttribute("msg","<h1>hello,SpringMVC<h1>"); return "hello"; } //真实访问的地址: 项目名/HelloController/Hello @RequestMapping("/hello1") public String sqyHello1(Model model){ model.addAttribute("msg","<h1>Hello,SpringMVC<h1>"); return "hello1"; } }
-
测试访问:https://localhost/hello / https://localhost/hello1
使用RestFul风格
public class RestFulController {
@RequestMapping("/commit/{p1}/{p2}")
//@PathVariable (value=)这里如果不写value默认就是变量的属性名
public String index(@PathVariable int p1, @PathVariable int p2, Model model){
int result=p1+p2;
//SpringMVC会自动实例化一个Model对象用于向视图中传值
model.addAttribute("msg","返回结果:"+result);
//返回视图位置
return "hello";
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9oFdCGBG-1658976511447)(http://peggy-m.oss-cn-hangzhou.aliyuncs.com/img/image-20220727161924316.png)]
- 关于RestFul,如果在请求时属于与响应对象的属性不一致就会出现400错误
使用method属性指定请求类型
指定请求谓词的类型如GET, POST, HEAD, OPTIONS, PUT,PATCH, DELETE, TRACE等
//请求方式为POST
@RequestMapping(value = "/hello2",method = {RequestMethod.POST})
public String sqyHello2(Model model){
model.addAttribute("msg","<h1>Hello,SpringMVC<h1>");
return "hello";
}
总结:
- Spring MVC 的 @RequestMapping 注解能够处理 HTTP 请求的方法, 比如 GET, PUT, POST, DELETE 以
及 PATCH。
ServletAP
设置ServletAPl,不需要视图解析器
- 通过HttpServletResponse进行输出
- 通过HttpServletResponse实现重定向
- 通过HttpServletResponse实现转发
@Controller
public class ResultGo {
@RequestMapping("/request/t1")
public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.getWriter().println("Hello,Spring By Servlet API");
}
@RequestMapping("/request/t2")
public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.sendRedirect("/index.jsp");
}
@RequestMapping("/result/t3")
public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
//转发
req.setAttribute("msg","/result/t3");
req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,rsp);
}
}
通过设置ServletAPl不用通过视图解析器直接就可以实现转发
Spring MVC
通过springMVC来实现转发和重定向-无需视图解析器;
- 重定向,不需要视图解析器,本质就是一个重新请求一个新的地方,所以这里需要对路径注意,可以重定向到另一个请求实现。
@Controller
public class ResultSpringMVC2 {
@RequestMapping("/rsm2/t1")
public String test1(){
//转发
//转发请求的时候需要开启我们的视图解析器
return "hello";
}
//重定向请求时的url的地址会发生改变
@RequestMapping("/rsm2/t2")
public String test2(){
//重定向
return "redirect:/index.jsp";
//return "redirect:hello.do"; //hello.do为另一个请求
}
}
处理提交数据
- 提交的域名名称和处理方法的参数名一致
提交数据 : http://localhost:8080/hello?name=kakarote
处理数据的方法:
@RequestMapping("/hello")
public String hello(String name){
System.out.println(name);
return "hello";
}
前台:无数据输出
后台:获取url请求携带的参数
- 提交的域名名称和处理方法的参数名称不一致
提交数据:
处理数据的方法:
@RequestMapping("/hellos")
//@RequestParam() 注解可以为提交接收对象匿名为url中提交的参数名称
public String hello(@RequestParam("username")String name){
System.out.println(name);
return "hello";
}
如果使用了RequestParam()注解,那么请求的URL地址中的参数必须使用匿名后的参数名
- 提交的是一个对象
- 实体类
public class Student {
private String name ;
private Integer age;
private String site;
有参|无参构造方法
set|get
toString方法
}
-
提交数据
http://localhost:8080/user?name=kakarote&age=10&site=globe
-
处理方法
@Controller public class ObjectResultControllerTest { @RequestMapping("/user") public String student(Student stu){ System.out.println(stu); return "hello"; } }
-
前台后台结果
如果传递的是对象,前台的传递的参数名必须与对象名一致,否则接收到的就时Null
数据显示到前端
第一种 ModelAndView
- 实现Controller重写handleRequest方法实现
- 所以对于注解Controller相当于该类实现了该接口
public class ControllerTest implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//返回一个视图对象
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","<h1>ControllerTest<h1>");
modelAndView.setViewName("hello");
return modelAndView;
}
}
第二种 ModeMap
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("name",name);
System.out.println(name);
return "hello";
}
第三种 Model
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
三种存储方式的对比
Model 只适用存储数据,所提供的方法比较少
ModelMap 继承了LinkedMap,除了实现了自身的一些方法以为,同样的继承了LinkedMap的方法与特性
ModelAndView 可以在存储数据的同时,进行返回的逻辑视图,进行展示层的跳转
中文乱码的一般处理方式
跳转页面代码
<body>
<form action="/e/t" method="post">
<input type="text" name="name">
<input type="submit">
</form>
</body>
控制跳转层代码
@Controller
public class Encoding {
@RequestMapping("/e/t")
public String test(Model model, String name){
model.addAttribute("msg","<h1>"+name+"<h1>");
return "test";
}
}
输出结果
对于中文乱码,在以前都是通过过滤器进行处理,但SpringMVC给我们提供一个过滤器,可以在web.xml中进行配置
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这样基本可以解决大多数的请求中文乱码问题