SpringMVC 注解实现参数映射
参考资料:https://spring-mvc.linesh.tw/
1. 请求参数映射
@RequestMapping
注解的作用是建立请求 URL 和处理方法之间数据的对应关系。
该注解可以作用在方法和类上:
- 作用在类上:一级访问目录
- 作用在方法上:二级访问目录
注意:/ 表示应用的根目录开始,路径上不能只写一个 /
1.1 RequestMapping
属性:
path: 指定请求路径的 url
value: value 属性和 path 属性是一样的
method: 指定该方法的请求方式
params: 指定限制请求参数的条件
headers: 发送的请求中必须包含的请求头
1.2 请求参数的映射
映射机制:
表单提交的数据都是 k=v 格式的,如 username=jack&password=123
SpringMVC 的参数映射过程是把表单提交的请求参数,作为控制器中方法的参数进行映射的
映射要求:
提交表单的name属性 和 形参的名称 必须相同
,否则获取到的为 null。
支持类型:
- 基本数据类型和字符串类型
- 实体类型(JavaBean)
- 集合数据类型(List、map集合等)
- 日期类型转换处理(Date)
1.2.1 基本类型/字符串属性封装
提交表单的name和参数的名称必须相同
的,区分大小写。
1.2.2 实体类属性封装
要求提交表单的 name 和 JavaBean 中的属性名称需要一致,如果一个 JavaBean 类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性
1.2.3 集合属性封装
list[index].属性名
map['key'].属性名
注意:如果请求参数是中文,可以在 web.xml 中配置 Spring 提供的字符集过滤器来解决中文乱码问题
User
@Data@NoArgsConstructor@AllArgsConstructorpublicclassUser{private Integer id;private String username;private String password;private List<Car> carList;private Map<String, Car> carMap;private Date birth;}
UserController
@Controller// spring 三层中的控制层注解@RequestMapping("/user")// 类上:指定控制器即 Servlet 的一级目录publicclassUserController{// <a href="user/login">登陆1</a>@RequestMapping("/login")// 方法上:指定控制器即 Servlet 的二级目录public Stringlogin(){
System.out.println("login...");return"/success.jsp";}//name=id 与形参 id 相同: <a href="user/test_param?id=2001">登陆2</a>@RequestMapping("/test_param")publicvoidtest_param(String id){
System.out.println("id="+ id);}// @RequestParam 注解映射 name 名称为相同:<a href="user/test_param2?id=2001&name=张三">登陆3</a>@RequestMapping("/test_param2")publicvoidtest_param2(@RequestParam("id") String uid, String name){
System.out.println("uid="+ uid+", name="+ name);}/**
* 实体类型 + 集合类型 + 日期类型的映射
* <form action="user/test_entity" method="get">
* 编号:<input type="text" name="id"> <br>
* 姓名:<input type="text" name="username"> <br>
* 密码:<input type="password" name="password"> <br>
* list:<input type="text" name="carList[1].cname"> <br>
* list:<input type="text" name="carList[2].cname"> <br>
* map: <input type="text" name="carMap['mycar'].cname"> <br>
*
* date:<input type="date" name="birth">
* <input type="submit">
* </form>
*/@RequestMapping("/test_entity")publicvoidtest_entity(User user){
System.out.println(user);}}
web.xml
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name>Archetype Created Web Application</display-name><!--配置中文乱码过滤器--><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><!--配置前端控制器--><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></web-app>
springmvc.xml
<!--开启注解扫描--><context:component-scanbase-package="com.demo"/><!--视图解析对象--><beanid="internalResourceViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/WEB-INF/jsp"/></bean><!--开启SpringMVC框架注解支持--><mvc:annotation-driven/>
1.2.4 Date类型封装
如果对象的属性中有Date类型,页面输入参数格式是 2019/1/1 可以自动参数映射,如果页面输入参数格式是 2019-1-1 则无法映射,需要使用自定义类型转换器来解决。
注意:表单提交的任何数据类型全部都是字符串类型,但是后台定义 Integer 类型,数据也可以封装上,说明 Spring 框架内部会默认进行数据类型转换。
如果想自定义数据类型转换,可以实现 Converter 的接口
。
- 创建日期转换工具类
//把字符串转换日期publicclassStringToDateConverterimplementsConverter<String, Date>{@Overridepublic Dateconvert(String s){if("".equals(s)){thrownewRuntimeException("日期字符串不能为空");}try{returnnewSimpleDateFormat("yyyy-MM-dd").parse(s);}catch(ParseException e){
e.printStackTrace();}thrownewRuntimeException("日期类型转换异常");}}
- 修改 springmvc.xml
<!--开启注解扫描--><context:component-scanbase-package="com.demo"/><!--视图解析对象--><beanid="internalResourceViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/WEB-INF/jsp"/></bean><!--配置自定义类型转换器 - 解决日期转换问题--><beanid="conversionServiceFactoryBean"class="org.springframework.context.support.ConversionServiceFactoryBean"><propertyname="converters"><set><beanclass="com.demo.utils.StringToDateConverter"/></set></property></bean><!--开启SpringMVC框架注解支持--><mvc:annotation-drivenconversion-service="conversionServiceFactoryBean"/>
1.3 常用注解
@RequestParam 注解
作用:把请求中的指定名称的参数传递给控制器中的形参赋值- value:请求参数中的名称
- required:请求参数中是否必须提供此参数,默认值是true,必须提供
@PathVariable 注解
作用:拥有映射 url 中的占位符的。url 中有 /delete/{id} ,{id} 就是占位符,也叫URI模板
- value:指定 url 中的占位符名称
jsp:<a href="user/testPathVariable/123">testPathVariable</a>
controller:@RequestMapping(value="/testPathVariable/{uid}")public StringtestPathVariable(@PathVariable(name="uid") String id){
System.out.println(id);// 123return"success";}
Restful 风格的 URL,即通过 PathVariable 实现:
请求路径一样,可以根据不同的请求方式去执行后台的不同方法,如京东的商品链接…
restful风格的URL优点:结构清晰、符合标准、易于理解、扩展方便
1.4 其他注解
- @RequestHeader 注解
作用:获取指定请求头的值- value:请求头的名称
jsp:<a href="user/testRequestHeader">RequestHeader</a>
controller:@RequestMapping(value="/testRequestHeader")public StringtestRequestHeader(@RequestHeader(value="Accept") String header){
System.out.println(header);// 打印 accept 的头信息return"success";}
- @CookieValue 注解
作用:用于获取指定cookie的名称的值- value:cookie的名称
jsp:<a href="user/testCookieValue">CookieValue</a>
controller:@RequestMapping(value="/testCookieValue")public StringtestCookieValue(@CookieValue(value="JSESSIONID") String cookieValue){
System.out.println(cookieValue);// session id值return"success";}
2. 响应数据和结果视图
2.1 返回值分类
String
Controller 方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址。
应用时可以设置参数类型为 Model,使用 Model 对象调用 addAttribute 方法来存储数据,同 request。request.setAttribute(“data”, data);
model.addAttribute(“data”, data);
void
如果控制器的方法返回值编写成 void,执行程序报 404 的异常,默认查找 JSP 页面没有找到。
应用时可以设置参数类型为 HttpServletRequest 和 HttpServletResponse,使用转发或者重定向来跳转页面ModelAndView
ModelAndView 对象是 Spring 提供的一个对象,可以调用 addObject 方法来保存数据以及调用 setViewName 方法来跳转页面。forward: &redirect: 前缀
可以在前端控制器的方法中直接返回 forward: 或 redirect: 为前缀的路径字符串,由 SpringMVC 反射中自动解析路径选择 转发或重定向 跳转页面。使用forward关键字进行请求转发:return “forward:转发的JSP路径”
使用redirect关键字进行重定向(
默认会把项目路径加上
):return “redirect:重定向的JSP路径”
User
@Data@NoArgsConstructor@AllArgsConstructorpublicclassUser{private Integer id;private String username;private String password;}
UserController
@Controller@RequestMapping("/user")publicclassUserController{public List<User>getUsers(){
List<User> list=newArrayList<User>();
list.add(newUser(1,"aaa","123"));
list.add(newUser(2,"bbb","456"));
list.add(newUser(3,"ccc","789"));return list;}// String 返回值跳转@RequestMapping("/testString")public StringtestString(HttpServletRequest request){
List<User> users=getUsers();
request.setAttribute("users", users);return"/list.jsp";}// void 无返回值跳转@RequestMapping("/testVoid")publicvoidtestVoid(HttpServletRequest request, HttpServletResponse response)throws Exception{
List<User> users=getUsers();
request.setAttribute("users", users);
request.getRequestDispatcher("/WEB-INF/jsp/list.jsp").forward(request, response);}// ModelAndView 返回值跳转@RequestMapping("/testModelAndView")public ModelAndViewtestModelAndView(){
List<User> users=getUsers();
ModelAndView modelAndView=newModelAndView();
modelAndView.addObject("users", users);
modelAndView.setViewName("/list.jsp");return modelAndView;}// forward / redirect 前缀指定 转发 或 重定向@RequestMapping("testForwardAndRedirect")public StringtestForwardAndRedirect(HttpServletRequest request){
List<User> users=getUsers();
request.getSession().setAttribute("users", users);return"forward:/index.jsp";//return "redirect:/index.jsp";}}
web.xml:中文乱码过滤器、前端控制器。
springmvc.xml
<!--开启注解扫描--><context:component-scanbase-package="com.demo"/><!--视图解析对象--><beanid="internalResourceViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><propertyname="prefix"value="/WEB-INF/jsp"/></bean><!--开启SpringMVC框架注解支持--><mvc:annotation-driven/>
3. 配置不拦截静态资源
DispatcherServlet 会拦截到所有的资源,导致一个问题就是静态资源 img、css、js 也会被拦截到,从而不能被使用。
解决方案就是需要配置静态资源不进行拦截,在 springmvc.xml 配置文件添加如下配置:
方式一:<mvc:resources>
+<servlet-mapping>
<!-- springmvc.xml 前端控制器,哪些静态资源不拦截--><mvc:resourceslocation="/css/"mapping="/css/**"/><mvc:resourceslocation="/images/"mapping="/images/**"/><mvc:resourceslocation="/js/"mapping="/js/**"/><!-- web.xml 配置 servlet 映射,html资源不被拦截 --><servlet-mapping><serlvet-name>default</serlvet-name><url-pattern>*.html</url-pattern></servlet-mapping>
方式二:所有静态资源不被拦截
<!-- springmvc.xml 所有静态资源不拦截--><mvc:default-servlet-handler/>