SpringMVC框架详解与实践指南
文章目录
- 一、三层架构与MVC模型
- 1. 三层架构
- 2. MVC模型
- 二、SpringMVC入门案例
- 1. 环境搭建
- 2. 核心配置
- 3. 编写Controller
- 三、执行流程与组件分析
- 四、RequestMapping注解
- 五、请求参数绑定
- 1. 基本类型与对象绑定
- 2. 嵌套对象与集合绑定
- 六、中文乱码解决方案(前端传到后端)
- 1. String转字节流(不推荐)
- 2. Servlet中配置编码
- 3. 过滤器(Filter)统一处理
- 方案一:Spring框架提供的过滤器(推荐)
- 方案二:自定义过滤器(处理GET/POST)
- 七、自定义类型转换器
- 1.使用DateTimeFormat注解的方式
- 2.自定义类型转换器
- 八、SpringMVC常用注解详解
- 1. @RequestParam注解
- 2. @RequestBody注解
- 3. @PathVariable注解与Restful风格URL
- 4. @RequestHeader注解
- 5. @CookieValue注解
- 总结
一、三层架构与MVC模型
1. 三层架构
表现层(WEB层):负责与客户端交互,采用MVC设计模型。
业务层:处理具体业务逻辑。
持久层:操作数据库。
2. MVC模型
Model:数据模型(如JavaBean),用于封装数据。
View:视图层(如JSP/HTML),展示数据。
Controller:控制器,接收请求并处理逻辑。
二、SpringMVC入门案例
1. 环境搭建
Maven依赖配置:
<properties><spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><!-- Servlet API --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope></dependency>
</dependencies>
2. 核心配置
web.xml:
<!-- 配置DispatcherServlet -->
<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:springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>*.do</url-pattern>
</servlet-mapping>
springmvc.xml:
<!-- 扫描Controller包 -->
<context:component-scan base-package="cn.tx"/>
<!-- 视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/pages/"/><property name="suffix" value=".jsp"/>
</bean>
3. 编写Controller
@Controller
public class HelloController {@RequestMapping("/hello.do")public String sayHello() {System.out.println("请求处理中...");return "suc"; // 跳转到 /WEB-INF/pages/suc.jsp}
}
三、执行流程与组件分析
- DispatcherServlet:前端控制器,接收请求。
- HandlerMapping:映射请求到具体方法。
- HandlerAdapter:调用处理器方法。
- ViewResolver:解析视图名称。
- View:渲染结果并响应。
四、RequestMapping注解
RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系。
RequestMapping注解可以作用在方法和类上。
作用在类上:第一级的访问目录
作用在方法上:第二级的访问目录
细节:路径可以不编写 / 表示应用的根目录开始
RequestMapping的属性
- path 指定请求路径的url
- value value属性和path属性是一样的(可隐藏)
- method 指定该方法的请求方式
method | 主要应用 |
---|---|
get | 查询 |
post | 增加 |
delete | 删除 |
put | 修改 |
- params 指定限制请求参数的条件
例:
@Controller
@RequestMapping("/user")
public class UserController {@RequestMapping(path = "/save.do",method = {RequestMethod.GET},params = "username")public String save(){System.out.println("保存角色...");return "suc";}}
五、请求参数绑定
1. 基本类型与对象绑定
JSP表单:
<form action="/user/save.do" method="post">姓名:<input type="text" name="username">年龄:<input type="text" name="age"><input type="submit" value="提交">
</form>
Controller接收:
@RequestMapping("/save.do")
public String saveUser(String username, Integer age) {System.out.println("用户名:" + username + ",年龄:" + age);return "suc";
}
2. 嵌套对象与集合绑定
JavaBean:
public class User {private String username;private Address address; // 嵌套对象private List<Address> list; // List对象集合private List<Strig> list1; // List字符串集合private Map<String, String> map; // Map集合
}
JSP表单:
<!-- 嵌套对象 -->
<input type="text" name="address.city">
<!-- List集合 -->
<input type="text" name="list[0].city">
<input type="text" name="list[1].city">
<input type="text" name="list1[0]">
<input type="text" name="list1[1]">
<!-- Map集合 -->
<input type="text" name="map['key1']">
<input type="text" name="map['key2']">
Controller接收:
@RequestMapping("/save1.do")public String save1(User user){System.out.println("user对象:"+user);return "suc";}
六、中文乱码解决方案(前端传到后端)
1. String转字节流(不推荐)
适用场景:GET请求参数乱码(不推荐,仅作临时方案)
实现原理:将接收到的参数从默认的ISO-8859-1编码转换为UTF-8
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"), "UTF-8");
缺点:需逐个参数处理,代码冗余,无法覆盖所有请求类型。
2. Servlet中配置编码
适用场景:POST请求的表单数据
实现原理:在Servlet的doPost方法中设置request和response编码。
// 在Servlet中配置
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");// 其他处理逻辑
}
配置位置:若使用SpringMVC,可在web.xml中全局配置:
<!-- 仅对POST有效 -->
<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>
局限性:无法解决GET请求的乱码问题(GET参数通过URL传递)。
3. 过滤器(Filter)统一处理
方案一:Spring框架提供的过滤器(推荐)
适用场景:所有请求类型(需额外处理GET)
配置方法:在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>
作用范围:自动处理所有请求和响应的编码,但对GET请求需结合Tomcat配置。
方案二:自定义过滤器(处理GET/POST)
适用场景:需要兼容GET请求且无法修改Tomcat配置时
实现步骤:
编写过滤器类:
public class CustomEncodingFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {// 设置请求编码request.setCharacterEncoding("UTF-8");// 处理GET请求参数(Tomcat 8+默认UTF-8,低版本需手动解码)if (request instanceof HttpServletRequest) {HttpServletRequest req = (HttpServletRequest) request;if ("GET".equalsIgnoreCase(req.getMethod())) {Map<String, String[]> params = req.getParameterMap();for (Map.Entry<String, String[]> entry : params.entrySet()) {String[] values = entry.getValue();for (int i = 0; i < values.length; i++) {values[i] = new String(values[i].getBytes("ISO-8859-1"), "UTF-8");}}}}// 设置响应编码response.setCharacterEncoding("UTF-8");chain.doFilter(request, response);}
}
配置web.xml:
<filter><filter-name>customEncodingFilter</filter-name><filter-class>com.example.CustomEncodingFilter</filter-class>
</filter>
<filter-mapping><filter-name>customEncodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
优点:全面覆盖GET/POST请求,兼容性更强。
七、自定义类型转换器
1.使用DateTimeFormat注解的方式
JavaBean:
public class User {
@DateTimeFormat(pattern = "yyyy-MM-dd")private Date birthday;
}
springmvc.xml:
<mvc:annotation-driven></mvc:annotation-driven>
JSP表单:
<<form action="/user/save2.do" method="post">生日:<input type="text" name="birthday" placeholder="yyyy-MM-dd"/><br/><input type="submit" value="提交" />
</form>
Controller接收:
@RequestMapping("/save2.do")public String save2(User user){System.out.println("user对象:"+user);return "suc";}
2.自定义类型转换器
StringToDate类:
package cn.tx.demo2.Date;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;/**** 自定义类型转换器 把String转换成Date*/
public class StringToDate implements Converter<String,Date>{/*** 进行类型转换的方法* @param s 用户输入的内容* @return*/@Overridepublic Date convert(String s) {// 判断if(s == null){throw new RuntimeException("请输入内容");}// 进行转换SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");try {// 进行转换return sdf.parse(s);} catch (ParseException e) {throw new RuntimeException(e);}}}
springmvc.xml:
<!--配置日期类型转换器,类型转换器的组件,把日期类型转换注入到组件对象中--><bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"><property name="converters"><set><bean class="cn.tx.demo2.Date.StringToDate" /></set></property></bean>
<!--让映射器、适配器和处理器生效(默认不配置也是可以的)--><mvc:annotation-driven conversion-service="conversionService"/>
八、SpringMVC常用注解详解
1. @RequestParam注解
@RequestParam
注解主要用于将请求中的指定名称参数传递给控制器的形参进行赋值。它包含以下属性:
value
:用于指定请求参数的名称;required
:表示请求参数是否为必须提供,默认值为true
,若设为false
,当请求中无对应参数时不会报错;defaultValue
:当请求中未传递该参数时,使用设置的默认值。
package cn.tx.demo3;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;@Controller
@RequestMapping("/dept")
public class DeptController {@RequestMapping("/save1.do")public String save(@RequestParam(value = "username", required = false, defaultValue = "abc") String name) {System.out.println("姓名:" + name);return "suc";}
}
在上述代码中,@RequestParam
注解将请求中的username
参数赋值给name
变量,若请求未携带username
参数,name
将使用默认值"abc"
。
2. @RequestBody注解
@RequestBody
注解用于获取请求体的内容,需要注意的是,该注解不适用于GET
请求。它只有一个required
属性,用于表示请求体是否为必须存在,默认值为true
。
@RequestMapping("/save2.do")
public String save2(@RequestBody String body) {System.out.println("请求体内容:" + body);return "suc";
}
通过@RequestBody
,可以方便地获取客户端在请求体中发送的数据,常用于处理JSON、XML等格式的请求数据。
3. @PathVariable注解与Restful风格URL
@PathVariable
注解用于绑定URL中的占位符,使URL中的参数能够传递到控制器方法中。其value
属性用于指定URL中占位符的名称。
Restful风格的URL具有结构清晰、符合标准、易于理解和扩展方便等优点,它可以根据不同的请求方式(如GET
、POST
、PUT
、DELETE
等),在相同的请求路径下执行后台不同的方法。
package cn.tx.demo3;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;@Controller
public class EmpController {@RequestMapping(path = "/emp", method = RequestMethod.POST)public String save() {System.out.println("保存员工...");return "suc";}@RequestMapping(path = "/emp", method = RequestMethod.GET)public String findAll() {System.out.println("查询员工...");return "suc";}@RequestMapping(path = "/emp/{id}", method = RequestMethod.GET)public String findById(@PathVariable(value = "id") Integer id) {System.out.println("通过id查询员工..." + id);return "suc";}
}
上述代码中,通过@PathVariable
获取URL中的id
参数,实现了根据不同的请求方式和参数执行相应业务逻辑。同时,为了更好地支持Restful风格URL,前端控制器的配置需将url-pattern
设为/
,以便更灵活地处理各类请求。
<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:springmvc.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>
4. @RequestHeader注解
@RequestHeader
注解用于获取指定请求头的值,通过value
属性指定请求头名称。
@RequestMapping("/save3.do")
public String save3(@RequestHeader(value = "Accept") String header) {System.out.println("Accept请求头的值:" + header);return "suc";
}
在实际开发中,该注解可用于获取诸如User - Agent
、Referer
等请求头信息,便于进行请求来源判断、客户端类型识别等操作。
5. @CookieValue注解
@CookieValue
注解用于获取指定Cookie
名称的值,通过value
属性指定Cookie
的名称。
@RequestMapping("/save4.do")
public String save4(@CookieValue(value = "JSESSIONID") String cookie) {System.out.println("值:" + cookie);return "suc";
}
利用该注解,可以方便地获取客户端发送的Cookie
信息,常用于用户会话管理、身份验证等场景 。
总结
SpringMVC通过清晰的组件分工简化了Web开发,结合参数绑定和视图解析器,能高效处理请求。中文乱码需根据场景选择方案,推荐使用过滤器。对于复杂数据(如Map),只需确保前端参数命名规范即可自动绑定。