SpringMVC@Controller学习笔记

    xiaoxiao2021-12-14  20



    SpringMVC的工作流程

    @Controller示例


    web.xml

    <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>springmvc-1</display-name> <!-- 防止中文参数乱码 放在前面 --> <filter> <filter-name>SetCharacterEncoding</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> <!-- 强制进行转码 --> </init-param> </filter> <filter-mapping> <filter-name>SetCharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置 HiddenHttpMethodFilter 可以把POST请求转为 DELETE 和 PUT请求 --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--配置DispatcherServlet --> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置DispatcherServlet 的一个初始化参数:配置SpringMVC 配置文件的位置和名称 --> <!-- 实际上也可以不通过 contextConfigLocation 来配置 SpringMVC 的配置文件 默认的配置文件路径为 /WEB-INF/{servlet-name}-servlet.xml 可以去除下面的<init-param> --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- Map all requests to the DispatcherServlet for handling --> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>

    springmvc.xml

    <?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:aop="http://www.springframework.org/schema/aop" 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/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd"> <!-- 配置自动扫描的包 --> <context:component-scan base-package="com.peng.springmvc"></context:component-scan> <!-- 配置视图解析器 如何把 handler 方法返回值解析为实际的物理视图 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"></property> <property name="suffix" value=".jsp"></property> </bean> <!--配置视图解析器 BeanNameViewResolver使用视图的名字来解析视图--> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"> <!-- 通过order 属性来定义视图解析器的优先级 ,order 值越小,优先级越高 --> <property name="order" value="100"></property> </bean> <!-- 配置国际化资源文件 --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="i18n"></property> </bean> <!-- 配置直接转发的页面--> <!-- 可以直接转发的页面,不经过handler--> <!-- 路径http://localhost:8082/springmvc-1/success 可以直接访问 /WEB-INF/views/success.jsp --> <mvc:view-controller path="/success" view-name="success"/> <!-- 实际开发中,通常需要配置 mvc:annotation-driven 标签 --> <mvc:annotation-driven></mvc:annotation-driven> </beans>

    SpringMVCTest.java

    package com.peng.springmvc.handlers; import java.io.IOException; import java.io.Writer; import java.util.Arrays; import java.util.Date; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.servlet.ModelAndView; import com.peng.springmvc.entities.User; @SessionAttributes(value={"user"},types={String.class})//声明了键名称和类型 @RequestMapping("/springmvc") @Controller public class SpringMVCTest { private static final String SUCCESS = "success"; /** *1.使用@RequestMapping 注解来映射请求的URL *2.返回值会通过试图解析器解析为实际的物理视图,对于InternalResourceViewResolver 视图解析器,会 * 做如下的解析 * prefix + returnVal + suffix 得到实际的物理视图,然后做转发操作 * /WEB-INF/views/success.jsp * @return */ @RequestMapping("/helloworld") public String hello(){ System.out.println("hello world"); return SUCCESS; } /** * @RequestMapping 除了修饰方法,还可以修饰类 * 类定义处:提供初步的请求映射信息,相对于 WEB 应用的根目录 * 方法定义处:提供进一步的映射信息,若类定义处为定义,则方法处相对于 WEB 应用的根目录 * @return */ @RequestMapping("/testRequestMapping") public String testRequestMaping(){ System.out.println("testRequestMapping"); return SUCCESS; } /** * @RequestMapping 的 value、method、params 及 heads分别表示 请求URL、请求方法、请求参数和请求头 * 映射条件,他们之间是与的关系,联合使用多分条件可以让请求映射更加精确化。 * @return */ @RequestMapping(value = "testMethod", method = RequestMethod.POST) public String testMethod(){ System.out.println("testMethod"); return SUCCESS; } /** * param1 要包含param1的参数 * !param1 不能包含param1的参数 * param1!=value1 param1参数不能等于 value1 * 请求头在浏览器开发者选项中可以查找 * @return */ @RequestMapping(value="testParamsAndHeaders",params={"username","age!=10"}, headers={"Accept-Language=zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3"}) public String testParamsAndHeaders(){ System.out.println("testParamsAndHeaders"); return SUCCESS; } /** * Ant风格 * ?匹配一个字符 * *匹配任意个字符 * **匹配多层路径 * @return */ // /user/**/aa 匹配 /user/aa/bb/cc/aa @RequestMapping("/testAntPath/*/abc") public String testAntPath(){ System.out.println("testAntPath"); return SUCCESS; } /** * @PathVariable 映射 URL绑定的占位符 * 带占位符的URL是 Spring3.0新增的功能,该功能在 SpringMVC向 REST 目标 * 发展中具有里程碑的意义 * 可以将 URL 的占位符参数绑定到控制器处理方法的入参中 * @param id * @return */ @RequestMapping("testpathVariable/{id}") public String testpathVariable(@PathVariable(value="id") Integer id){ System.out.println("testpathVariable"+id); return SUCCESS; } /** * @RequestParam 映射请求参数 * value 值即为请求参数的参数名 * required 该参数是否为必须 默认为true * defaultvalue 请求参数的默认值 * @param * @param age * @return */ @RequestMapping(value="/testRequestParam") public String testRequestParam(@RequestParam(value="username")String un, @RequestParam(value="age",required=false)Integer age){ System.out.println("testRequestParam "+un+" "+age); return SUCCESS; } /** * @RequestHeader 请求头信息 * @param al * @return */ @RequestMapping(value="/testRequestHeader") public String testRequestHeader(@RequestHeader(value="Accept-Language") String al){ System.out.println("testRequestHeader Accept-Language: "+ al); return SUCCESS; } /** * Rest风格的URL * 以CRUD为例 * 新增:/order POST * 修改:/order/1 PUT update?id=1 * 获取:/order/1 GET get?id=1 * 删除:/order/1 DELETE delete?id=1 * * 要发送 PUT 和DELETE 请求 * 1.配置 HiddenHttpMethodFilter * 2.需要发送POST请求,请求是携带 name="_method" 的隐藏域 值为 put 或 delete * 方法中传入参数用到 @PathVariable 注解 * @param id * @return */ @RequestMapping(value="/testRest/{id}",method=RequestMethod.GET) public String testRest(@PathVariable Integer id){ System.out.println("testRest GET"+id); return SUCCESS; } @RequestMapping(value="/testRest",method=RequestMethod.POST) public String testRestPOST(){ System.out.println("testRest POST"); return SUCCESS; } @RequestMapping(value="/testRest/{id}",method=RequestMethod.DELETE) public String testRestDELETE(@PathVariable Integer id){ System.out.println("testRest DELETE"+id); return SUCCESS; } @RequestMapping(value="/testRest/{id}",method=RequestMethod.PUT) public String tesPUTt(@PathVariable Integer id){ System.out.println("testRest PUT"+id); return SUCCESS; } /** * @CookieValue 映射一个Cookie值 * 事先要知道cookie的名称 * 在浏览器的开发者选项中 网络中 查看 */ @RequestMapping(value="/testCookieValue") public String testCookieValue(@CookieValue("JSESSIONID") String sessionID){ System.out.println("testCookieValue JSESSIONID: "+ sessionID); return SUCCESS; } /** * SpringMVC 会按请求参数名和POJO 属性名进行自动匹配,自动为该对象填充属性值 * 支持级联属性 如:address.city address.provice * @param user * @return */ @RequestMapping(value="/testPojo") public String testPojo(User user){ System.out.println("testPojo"+user.toString()); //不支持中文 return SUCCESS; } /** * 可以使用 servlet 原生的API 作为目标方法的参数 * 具体支持以下类型 * HttpServletRequest * HttpServletResponse * HttpSession * java.security.Principal * Locale * InputStream OutputStream * Reader Writer * * @throws IOException */ @RequestMapping("/testServletAPI") public void testServletAPI(HttpServletRequest request, HttpServletResponse response,Writer out) throws IOException{ System.out.println("testServletAPI "+request+" "+response); out.write("hello Springmvc"); //return SUCCESS; } /* -------------处理模型数据-------------------*/ /** * 目标方法的返回值可以是 ModelAndView 类型 * 其中可以包含视图和模型信息 * SpringMVC 会把 ModelAndVew 的 model 中数据放入 request 域对象中 * @return */ @RequestMapping("/testModelAndView") public ModelAndView testModelAndView(){ String viewName = SUCCESS; ModelAndView modelAndView = new ModelAndView(viewName); //添加模型数据到 ModelAndView中 modelAndView.addObject("time",new Date()); return modelAndView; } /** * 目标方法可以添加 Map类型(实际上也可以是 Model类型或 ModelMap 类型)的参数 * @param map * @return */ @RequestMapping("/testMap") public String testMap(Map<String,Object> map){ System.out.println(map.getClass().getName());//BindingAwareModelMap map.put("names", Arrays.asList("tom","jerry","hellly")); return SUCCESS; } /** * @SessionAttributes 除了可以通过属性名指定需要存放到会话中的属性外(使用的是value属性值), * 还可以通过模型属性的对象类型指定哪些模型属性需要放到会话中(实际上使用的是types属性值) * 注意:该注解只能放在类的上面 * @SessionAttributes(value={"user"},types={String.class}) * @param map * @return */ @RequestMapping("/testSessionAttributes") public String testSessionAttributes(Map<String,Object> map){ User user = new User("tom","123","23@qq.com"); map.put("user",user);//存放在request 请求域中 map.put("school", "jxust"); /** * 类上加上@SessionAttributes({"user"}) 同时也会存放在 session域中 */ return SUCCESS; } /** * 1.由@ModelAttribute 标记的方法,会在每个目标方法执行之前被 SpringMVC调用! * 2.@ModelAttribute 注解也可以来修饰目标方法 POJO 类型的入参,其value 属性值有如下作用: * 1).SpringMVC 会使用value 属性值在 ImplicitModel 中查找对应的对象,若存在则会直接传入到目标方法的入参中. * 2).SpringMVC 会把 value 为 Key ,POJO类型的对象为value,存入到request中 * @param id * @param map */ //若@SessionAttributes设置了请求参数相同的对象 如testModelAttribute的User,就必须用@ModelAttribute区分,防止异常 @ModelAttribute public void getUser(@RequestParam(value="id",required=false) Integer id, Map<String,Object> map){ System.out.println("@ModelAttribute method"); if(id !=null){ //模拟从数据库获取对象 User user = new User(1,"tom","12345","tom@qq.com"); System.out.println("从数据库中获取一个对象"+user); map.put("user", user);//键:类名小写 } } /** * 运行流程: * 1.执行 @ModelAttribute 注解修饰的方法,从数据库中取出对象,把对象放到 Map中,键为:user * 2.SpringMVC 从 Map 中取出 User 对象,并把表单的请求参数赋给该 User 对象的对应属性 * 3.SpringMVC 把上述对象传入目标方法的参数。 * 注意:在@ModelAttribute 修饰的方法中,放入到Map中的键需要和目标方法入参类型的第一个字母小写的字符串一致! * * SpringMVC 确定目标方法 POJO 类型入参的过程 * 1.确定一个key * 1).若目标方法的 POJO 类型参数没有使用 @ModelAttribute 作为修饰,则 key 为 POJO 类名第一个字母小写 * 2).若使用了 @ModelAttribute 注解,则 key为 该注解 value 属性值 * * 2.在 implicitModel 中查找 key 对应的对象,若存在,则作为入参传入 * 1).若在 @ModelAttribute 标记的方法中保存过,且 key 和1确定的 key 一致,则会获取到 * * 3.若 implicitModel 中不存在 key 对应的对象,则检查当前的 Handler 是否使用 @SessionAttributes 注解修饰, * 若使用了该注解,且 @SessionAttributes 注解的value 属性值中包含了key,则会从 HttpSession 中来获取 key 所 * 对应的 value 值,若存在则直接传入到目标方法的入参中,若不存在则抛出异常 * 4. 若 Handler 没有标识 @SessionAttributes 注释或 @SessionAttributes 注解的value 值中不包含 key,则会通过反射 * 来创建 POJO 类型的参数,传入目标方法的参数 * 5.SpringMVC 会把 key 和 POJO 类型的对象保存到 implicitModel 中,进而会保存到 request 中 * * 源码流程: * 1.调用@ModelAttribute 注解修饰的方法,实际上把@ModelAttribute 方法中 Map中的数据中的数据放在 implicatModel 中, * 2.解析请求处理器的目标参数,实际上给目标参数来自于 WebDataBinder 对象的 target 属性 * 1).创建WebDataBinder * ①确定objectName 属性:若传入的attrName 属性值为 "" ,则objectName 为类名第一个字母小写 * 注意: attrName 若目标方法的 POJO 属性使用了@ModelAttribute来修饰,则 attrName 值即为@ModelAttribute * 的value值 * * ②确定target属性 * >在 implicitModel 中查找 attrName 对应的属性值,若存在,ok * >若不存在:则验证当前Handler 是否使用 @SessionAttributes 进行修饰,若使用了,则参数从Session中 * 获取 attrName 所对应的属性值,若session中没有对应的属性,则抛出了异常 * >若 Handler 没有使用@SessionAttributes 进行修饰,或@SessionAttributes 中没有使用value 值指定的 Key * 和 attrName 相匹配,则通过放射创建了 POJO对象 * 2).SpringMVC 把表单的请求参数赋给了 WebDataBinder 的 target 对应的属性 * 3).SpringMVC 会把WebDataBinder 的attrName 和 target 给到 implicitModel,进而传到request域对象中 * 4).把WebDataBinder 的 target 作为参数传递给目标方法的入参。 * @param user * @return */ @RequestMapping("/testModelAttribute") public String testModelAttribute(User user){ System.out.println("修改:"+user); return SUCCESS; } /* -------------处理模型数据-------------------*/ /** * JSTLView 导入了jstl.jar standard.jar * @return */ @RequestMapping("/testViewAndViewResolver") public String testViewAndViewResolver(){ System.out.println("testViewAndViewResolver"); return SUCCESS; } /** * 自定义视图 * @return */ @RequestMapping("/testView") public String testView(){ System.out.println("testView"); return "helloView"; } /** * 重定向和转发 * redirect:/index.jsp * forward:/index.jsp * @return */ @RequestMapping("/testRedirect") public String testRedirect(){ System.out.println("testRedirect"); return "redirect:/index.jsp"; } }

    POJO类

    Address.java

    package com.peng.springmvc.entities; public class Address { private String province; private String city; public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "Address [province=" + province + ", city=" + city + "]"; } }

    User.java

    package com.peng.springmvc.entities; public class User { private Integer id; private String username; private String password; private String email; private Address address; public User() { super(); } public User(Integer id, String username, String password, String email) { super(); this.id = id; this.username = username; this.password = password; this.email = email; } public User(String username, String password, String email) { super(); this.username = username; this.password = password; this.email = email; } //省略 setter and getter @Override public String toString() { return "User [id=" + id + ", username=" + username + ", password=" + password + ", email=" + email + ", address=" + address + "]"; } }

    自定义视图

    HeloView.java

    package com.peng.springmvc.views; import java.util.Date; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.servlet.View; @Component public class HelloView implements View{ @Override public String getContentType() { return "text/html"; } @Override public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { response.getWriter().print("hello view,time: "+new Date()); } }

    i18n_en_US.properties

    i18n.username=Username i18n.password=Password

    Ii18n_zh_CN.properties

    i18n.username=\u7528\u6237\u540D i18n.password=\u5BC6\u7801

    index.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <a href="springmvc/testRedirect">TEST Redirect( 重定向和转发forward)</a><br> <a href="springmvc/testView">TEST View(自定义视图)</a><br> <a href="springmvc/testViewAndViewResolver">TEST ViewAndViewResolver(JSTLView 导入了jstl.jar standard.jar)</a><br> <!-- 模拟修改操作 1.原始数据 1,tom,12345,tom@qq.com 2.密码不能被修改 3.表单回显,模拟操作直接在表单填写对应的属性值 --> <form action="springmvc/testModelAttribute"> <input type="hidden" name="id" value="1"/> username:<input type="text" name="username" value="tom"/><br> email:<input type="text" name="email" value="tom@qq.com"/><br> <input type="submit" value="submit(@ModelAttribute 标记的方法,会在每个目标方法执行之前被 SpringMVC调用)"/> </form> <hr> <a href="springmvc/testSessionAttributes">TEST SessionAttributes(@SessionAttributes指定值、类型)</a><br> <a href="springmvc/testMap">TEST Map( 目标方法可以添加 Map类型)</a><br> <a href="springmvc/testModelAndView">TEST ModelAndView(返回值可以是 ModelAndView 类型)</a><br> <a href="springmvc/testServletAPI">TEST ServletAPI(可以使用 servlet 原生的API 作为目标方法的参数)</a><br> <hr> <form action="springmvc/testPojo" method="post"> username:<input type="text" name="username"/> <br> password:<input type="password" name="password"/> <br> email:<input type="text" name="email"/> <br> city:<input type="text" name="address.city"/> <br> province:<input type="text" name="address.province"/> <br> <input type="submit" value="submit(POJO类参数自动匹配)"/> </form> <hr> <a href="springmvc/testCookieValue">Test CookieValue(映射一个Cookie值)</a><br> <br> <a href="springmvc/testRequestHeader">Test RequestHeader(请求头信息)</a><br> <br> <a href="springmvc/testRequestParam?username=peng&age=12">Test RequestParam(映射请求参数)</a><br> <br> <hr> 测试4种请求<br> <a href="springmvc/testRest/1">Test Rest GET</a><br> <form action="springmvc/testRest" method="post"> <input type="submit"value="Test Rest POST"/> </form><br> <form action="/springmvc/testRest/2" method="post"> <input type="hidden" name="_method" value="delete"/> <input type="submit" value="Test Rest DELETE"/> </form> <br> <form action="/springmvc/testRest/3" method="post"> <input type="hidden" name="_method" value="put"/> <input type="submit"value="Test Rest PUT"/> </form><br> Tomcat8.0不支持put和 delete,会报错,Tomcat7又不支持文本3.1 \(^o^)/~ 修改到项目根目录下有一个.settings的文件夹 org.eclipse.wst.common.project.facet.core.xml文件中 修改 installed facet="jst.web" version="3.0" <hr> <a href="springmvc/helloworld">Hello World</a><br> <a href="springmvc/testRequestMapping">testRequestMapping(@RequestMapping注解可以定义在类和方法上)</a><br> <a href="springmvc/testMethod">testMethod(发送的是GET请求,接收的要是POST请求,不能跳转)</a><br> <form action="springmvc/testMethod" method="post"> <input type="submit"value="(testMethod,发送的是POST请求,接收的要是POST请求,可以跳转)"/> </form><br> <a href="springmvc/testParamsAndHeaders?username=peng&age=11">testParamsAndHeaders(请求头和请求参数)</a><br> <a href="springmvc/testAntPath/jifd/abc">testAntPath/*/abc(Ant风格路径)</a><br> <a href="springmvc/testpathVariable/1">/testpathVariable/1(@PathVariable占位符绑定参数表)</a><br> </body> </html>

    success.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h3>Success page</h3> 访问作用域范围的隐含对象time:${requestScope.time }<br> names:${requestScope.names}<br> request user:${requestScope.user }<br> session user:${sessionScope.user }<br> request school:${requestScope.school }<br> session school:${sessionScope.school }<br> session abc :${requestScope.abc }<br> session mxlg:${requestScope.mxlg }<br> <hr> <!-- 国际化 --> <fmt:message key="i18n.username"></fmt:message><br> <fmt:message key="i18n.password"></fmt:message><br> </body> </html>
    转载请注明原文地址: https://ju.6miu.com/read-967992.html

    最新回复(0)