1、SpringMVC简介
1.1、概念
SpringMVC的正式名称是Spring Web MVC
,是属于Spring
框架的一部分,是基于Servlet API
的Web
框架
SpringMVC
的核心功能是:拦截和处理客户端的请求
1.2、基本使用
1、在pom.xml
中添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
spring-webmvc
的依赖项:
spring-aop
、spring-beans
、spring-context
、spring-core
、
spring-expression
、spring-web
2、在web.xml
中配置
<!-- 配置SpringMVC自带的DispathcerServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- Spring的配置文件位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 拦截所有请求-->
<url-pattern>/</url-pattern>
</servlet-mapping>
3、在applicationContext.xml
中配置
<context:component-scan base-package="com.sj" />
4、创建Controller
@Controller
public class UserController {
@RequestMapping("/addUser")
@ResponseBody
public String add() {
return "Add Success!";
}
}
当调用post
请求时,就会调用Controller
中的add
方法
5、@RequestMapping
@RequestMapping
可以用在类,方法上
@GetMapping
、@PostMapping
可以用在方法上,底层是基于@RequestMapping
@Controller
@RequestMapping("/user")
public class UserControllerMethod {
@RequestMapping(value = "/addUser", method = RequestMethod.POST)
@PostMapping("/add")
@ResponseBody
public String add() {
return "Add Success!";
}
// 多个路径 /get 和 /list都会调用
@GetMapping({"/get", "/list"})
@ResponseBody
public String get() {
return "user get Success!";
}
}
1.3、请求参数
1、默认情况下,SpringMVC
会主动传递一些参数给请求方法
WebRequest
、HttpServletRequest
、HttpServletResponse
、HttpSession
@Controller
@RequestMapping("/skill")
public class SkillController {
@RequestMapping("/add")
@ResponseBody
public String add(HttpServletRequest request,
HttpServletResponse response,
HttpSession session,
WebRequest request2) {
return "SkillController add";
}
}
2、默认情况下,请求参数会传递给同名的方法参数
可以通过@RequestParam
指定方法参数对应的请求参数名
required
属性为false
:请求参数是可选的,客户端可以不传
required
属性为false
:请求参数是必须的,客户端必须传,否则出现400错误
可以通过Model
对象去接收请求参数
Model
对象的属性名需要和请求参数名保持一致
public class SkillController {
@RequestMapping("/save")
@ResponseBody
public String save(@RequestParam(value = "name", required = false) String name,
String intro,
int level) {
return "SkillController add";
}
}
4、请求路径变量
如果请求路径中的内容是变化的,可以定义成{变量名},然后通过使用@PathVariable
去获取值
// 浏览器中路由为
// http://localhost:8080/mvc01/skill/get/12
public class SkillController {
@RequestMapping("/get/{id2}")
@ResponseBody
public String get(@PathVariable("id2") Integer id) {
return "SkillController add" + id;
}
}
5、利用反射获取参数名
从JDK8
开始,可以通过java.lang.reflect.Parameter
类获取参数名称
前提:在编译*.java
的时候保留参数名信息到*.class
中,比如javac -parameters *.java
可以通过javap -v *.class
查看class
文件的参数名信息
对以下代码进行编译
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class TestParams {
public void run(String name, int age) {}
public static void main(String[] args) throws Exception {
Method method = TestParams.class.getMethod("run", String.class, int.class);
for (Parameter parameter: method.getParameters()) {
System.out.println(parameter.getName());
}
}
}
-
javac TestParams.java
、javap -v TestParams
#javac
public void run(java.lang.String, int);
descriptor: (Ljava/lang/String;I)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=0, locals=3, args_size=3
0: return
LineNumberTable:
line 9: 0
-
javac -parameters TestParams.java
、javap -v TestParams.class
#javac -parameters
public void run(java.lang.String, int);
descriptor: (Ljava/lang/String;I)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=0, locals=3, args_size=3
0: return
LineNumberTable:
line 4: 0
MethodParameters:
Name Flags
name
age
-
Maven
编译,获取Maven
的TestParams.class
文件
public void run(java.lang.String, int);
descriptor: (Ljava/lang/String;I)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=0, locals=3, args_size=3
0: return
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Lcom/sj/TestParam;
0 1 1 name Ljava/lang/String;
0 1 2 age I
SpringMVC
内部通过PrioritizedParameterNameDiscover
类获取参数名
1.4、乱码处理
1)、get
请求参数乱码
在Tomcat8
开始已经没有这个问题
Tomcat8
以前的解决方案是,在TOMCAT_HOME/conf/server.xml
中给Connector
标签增加属性URIEncoding="UTF-8"
<Connector port="8080" ... URIEncoding="UTF-8" />
2)、post
乱码问题
通过filter拦截请求,调用request.setCharacterEncoding("UTF-8");
在SpringMVC
中内置了这样的Filter
,直接在web.xml
配置即可使用
<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>
3)、响应乱码
@Controller
@RequestMapping("/encoding")
public class EncodingController {
// 指定编码规则,默认是 text/html
@RequestMapping( value = "/get",produces = "text/html; charset=UTF-8")
@ResponseBody
public String get() {
return "我是小明";
}
}
或者在applicationContext.html
中添加<mvc:annotation-driven>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
1.5、Servlet
的url
匹配 - *.do
、/
、/*
的区别
1、*.do
不会拦截动态资源(比如*.jsp
)、静态资源(比如*.html
、*.js
)
2、/
会拦截静态资源(比如*.html
、*.js
),不会拦截动态资源(比如*.jsp
)
Tomcat
内部两个默认的拦截器
1)、org.apache.catalina.servlets.DefaultServlet
,url-pattern
是/
所有.jsp
文件的拦截都会被JspServlet
拦截
2)、org.apache.jasper.servlet.JspServlet
,url-pattern
是*.jsp
和*.jspx
3、/*
会拦截动态资源(比如*.jsp
)、静态资源(比如*.html
、*.js
)一般用在Filter
中
@Controller
public class DoController {
// 匹配所有.jsp文件
@RequestMapping("/{filename}.jsp")
@ResponseBody
public String test3(@PathVariable String filename) {
return filename;
}
}
静态资源被拦截的解决方案1
1、如果SpringMVC
的DispatcherServlet
的url-pattern
设置为/
,会导致静态资源被拦截
解决方案:将静态资源交回给Tomcat
的DefaultServlet
去处理
<!--静态资源默认交回给servlet处理-->
<mvc:default-servlet-handler default-servlet-name="default"/>
2、<mvc:default-servlet-handler/>
的原理
会通过DefaultServletHttpRequestHandler
对象将静态资源转发给Tomcat
的DefaultServlet
3、使用<mvc:default-servlet-handler/>
后,会导致controller
无法处理请求
加上<mvc:annotation-driven>
后,可以保证controller
正常使用
静态资源被拦截的解决方案2
1、由 SpringMVC
框架内部来处理静态资源(内部通过ResourceHttpRequestHandler
对象)
<!--mapping 是请求路径-->
<!--location 是静态资源的位置-->
<mvc:resources mapping="/asset/**" location="/asset/" />
2、同样需要加上<mvc:annotation-driven>
,可以保证controller
正常使用
网友评论