Spring MVC
Spring MVC
官方文档:https://docs.spring.io/spring/docs/5.3.0-SNAPSHOT/spring-framework-reference/web.html#spring-web
MVC
Model (javabean)
View (jsp,freemaker,thymeleaf)
Controller (servlet controller)
Servlet实现Web应用:
IDEA开发:
新建普通项目-->右键添加框架支持 -->选择WebApplication-->编辑配置文件-->+ Tomcat配置
HelloServlet.java:
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getParameter("method");
if(method.equals("add")){
req.getSession().setAttribute("msg","执行了add方法");
}else if(method.equals("delete")){
req.getSession().setAttribute("msg","执行了delete方法");
}
System.out.println("doGet");
//转发
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(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>
<servlet-name>hello</servlet-name>
<servlet-class>com.yan.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
/WEB-INF/jsp/test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
$END$
</body>
</html>
SpringMVC运行原理图
官方:
详细原理:
初步使用SpringMVC
IDEA配置 :
新建maven项目-->添加框架支持 -->选择 WebApplication-->web.xml中配置dispatcherServlet(SpringMVC配置文件位置)-->建立spring-mvc-servlet.xml文件 -->配置处理器映射器,处理器适配器,视图解析器-->编写Controller-->配置 Controller bean-->编辑项目结构-->到Artifacts下,在WEB-INF 下新建lib目录并导入依赖包
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>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc-servlet.xml</param-value>
</init-param>
<!-- 启动级别 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-mvc-servlet.xml
<!-- 配置处理器映射器-->
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 配置处理器适配器-->
<bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 配置视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--配置Controller-->
<bean id="/hello" class="com.yan.controller.HelloController"/>
HelloController.java
public class HelloController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("msg","helloSpringMVC");
modelAndView.setViewName("hello");
return modelAndView;
}
}
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
小问题
其中/和/*的区别:
< url-pattern >/</ url-pattern > 不会匹配到*.jsp,即:*.jsp不会进入spring的 DispatcherServlet类 。
< url-pattern > /*</ url-pattern > 会匹配*.jsp,会出现返回jsp视图时再次进入spring的DispatcherServlet 类,导致找不到对应的controller所以报404错。
使用注解Controller
改动:
spring-mvc-servlet.xml
<!--扫描 注解包-->
<context:component-scan base-package="com.yan.controller"/>
<!-- 让Spring不处理静态资源 -->
<mvc:default-servlet-handler/>
<!-- MVC注解驱动-->
<mvc:annotation-driven/>
<!-- 处理器映射器-->
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 处理器适配器-->
<bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!-- 配置视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--配置Controller-->
<bean id="/hello" class="com.yan.controller.HelloController"/>
AnnotationController.java
@Controller
public class AnnotationController {
@RequestMapping("/annotation")
public String hello(Model model){
model.addAttribute("msg","AnnotationController.hello");
System.out.println("AnnotationController.hello");
return "hello";
}
}
细节问题
@PathVariable
例子:
@RequestMapping("/count/{a}/{b}")
public String add(@PathVariable Integer a,@PathVariable Integer b,Model model){
model.addAttribute("result",a+b);
return "result";
}
请求 :
http://localhost:8080/count/1/2
路径参数可以绑定到方法变量上
转发,重定向:
1.使用HttpServletRequest和HttpServletResponse
@RequestMapping("/origin")
public void origin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// request.setAttribute("msg","origin");
// request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request,response);
response.sendRedirect("http://www.baidu.com");
}
2.使用SpringMVC转发和重定向(无需视图解析器)
@RequestMapping("/mvc")
public String mvc(Model model) throws ServletException, IOException {
model.addAttribute("result",3);
//转发1
//return "/WEB-INF/jsp/result.jsp";
//转发2
//return "forward:/WEB-INF/jsp/result.jsp";
//重定向
return "redirect:http://www.baidu.com";
}
配置视图解析器后 转发1 会被拼接前后缀
参数绑定 :
参数名对应请求方法上的参数名,直接绑定
@RequestMapping("/param")
public String param(String name){
System.out.println(name);
return "hello";
}
请求:
http://localhost:8080/param?name=yan
参数名对应请求方法上的参数但名字不同,用@RequestParam重命名
@RequestMapping("/param")
public String param(@RequestParam("username") String name){
System.out.println(name);
return "hello";
}
请求:
http://localhost:8080/param?username=yan
对象:
@RequestMapping("/param")
public String param(User user){
System.out.println(user);
return "hello";
}
User.java
public class User {
private String name;
private int age;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
请求:
http://localhost:8080/param?name=yan&age=1
编码问题 :
配置SpringMVC编码过滤器:
<filter>
<filter-name>encodingFilter</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>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>