SpringMvc从菜鸟到大拿完成蜕
- 介绍
- Why springmvc
- Servlet缺点:
- servlet中的service:方法一次只能处理一类请求;单拿用户表来说,得需要创建五个Servlet;在url中输入的是urlpattern;默认只访问service方法;如何减少Servlet的个数呢?
增加了一个method参数;其他人有可能会喜欢叫oper;method名字随便起;
用户列表 | /AdminsBackServlet?method=adminsList |
用户添加 | /AdminsBackServlet?method=adminsInsert |
用户添加提交 | /AdminsBackServlet?method=adminsInsertSubmit |
用户更新 | /AdminsBackServlet?method=adminsUpdate |
用户更新提交 | /AdminsBackServlet?method=adminsUpdateSubmit |
用户删除 | /AdminsBackServlet?method=adminsDelete |
- 所有的servlet都得在web.xml中配置;一个项目有n个人开发;多个人同时修改一个文件;拆分文件;SpringMVC依托于Spring,Spring就支持配置文件拆分;
- 用户添加提交:里面包含了Servlet最全的代码;把Service和jsp连接起来了_*********
- 接收参数
- 处理参数(接收的参数全部是String)
- New一个对象
- 为对象赋值
- 调用Service的方法
- 将Service执行的结果存储到四大作用域;
- 文件上传的代码;commonfileupload
- 文件上传;如何接收二进制图片,如何接收字符串
- 上传文件限制大小
- 上传文件限制格式
- 过滤器也有不足
- 过滤器要拦截路径;路径里面支持*吗?文件名+*;/back*/head/*
- 过滤器new对象是tomcat new的,也需要调用Service查询数据库;(service交给了spring),过滤器咋办
-
- 介绍:
- SpringMVC它是一个mvc框架,开发模式;依托Spring,springmvc只需要一个jar包就可以;已经放到sping必须的包里面;
- Struts1,技术并不是很好;webwork;struts2+webwork结合起来出了一个struts2;
- springmvc有spring;spring把springmvc捧起来;三大框架整合的时候Spring不可替代;整合框架总是出现各种问题;纯Spring+springmvc spring团队,内部已经做过整合的问题;
- 流程
- 核心的Servlet:DispatcherServlet;父类是:FrameworkServlet;父类是:HttpServletBean;的父类是HttpServlet
- 先执行FrameworkServlet的service方法;有一段代码:super.service();
- 因为有了super.service方法,用户请求的时候先执行service方法,然后再执行dopost或者doget方法,doget调用了processRequest的doService(抽象的)
- DispatcherServlet中的doService(非抽象的),此方法中的doDispatch
处理器:
适配器
ModelAndView:
XML的适配器:
- 不用再写处理器和适配器了,因为SpringMVC已经默认配置好了
spring-webmvc-5.0.2.RELEASE.jar:/org/springframework/web/servlet/DispatcherServlet.properties
BeanNameUrlHandlerMapping:xml将bean的name和url关联起来;
RequestMappingHandlerMapping:注解中的requestMapping;类上面的requestMapping+方法上面的requestmapping;
就是从JSP-->Servlet;要把JSP的参数,变成JAVA的对象;
- 专门是为了解决此不足:
- 接收参数
- 处理参数(接收的参数全部是String)
- New一个对象
- 为对象赋值
- 调用Service的方法
- 将Service执行的结果存储到四大作用域;
- http请求不管是get还是post,发送的参数格式都是(字符串):
http://localhost:8080/项目名/a.html?a=1&b=2&c=3 |
- 实战
- Hw
- 创建一个web项目;一定要将项目发布到tomcat上,试着访问一下,不能出现404
- Web项目支持SpringMVC
- 添加jar包;将spingaop所需要的jar包,拷贝过来;
- 修改配置文件;
- Log4j2.xml;
<?xml version="1.0" encoding="UTF-8"?> <!-- status=debug 可以查看log4j的装配过程 --> <configuration status="off" monitorInterval="1800"> <appenders> <!-- 定义控制台输出 --> <Console name="Console" target="SYSTEM_OUT" follow="true"> <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" /> </Console> <!-- 系统打印日志 ,按照天记录日志;filePattern文件的格式--> <RollingRandomAccessFile name="System" fileName="logs/system.log" filePattern="logs/system_%d{yyyy-MM-dd}_%i.log"> <!-- 日志文件中内容的格式 --> <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" /> <Policies> <!-- 一天记录的日志如果大于100m,重新再创建一个新的日志 --> <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <SizeBasedTriggeringPolicy size="100M" /> </Policies> </RollingRandomAccessFile> </appenders> <loggers> <!-- Root Logger --> <root level="info"> <!-- 引入了一个Console和System --> <appender-ref ref="Console" /> <appender-ref ref="System" /> </root> <!-- 外部日志,只记录到文件中,不记录到控制台中 --> <logger name="SystemLog" level="info" additivity="false"> <appender-ref ref="System" /> </logger> </loggers> </configuration> |
-
-
- 修改web.xml;web项目启动的时候加载web.xml,如果web.xml里面啥也木有
- 写,springmvc拷贝了jar包也木有用;
-
<?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" version="3.1"> <display-name>springmvc-01-hw</display-name> <!-- 只能写servlet,filter,listener --> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 初始化参数 此参数只能是此Servlet使用 context-param:所有的Servlet都能使用 --> <init-param> <!-- contextConfigLocation:上下文的配置位置 Spring配置文件的路径: 从哪些地方加载Spring的配置文件 --> <param-name>contextConfigLocation</param-name> <!-- 从classpath中找配置文件 第一个*:表示从所有的classpath中找配置文件(包含jar包里面的) 第二个*:通配 --> <param-value>classpath*:applicationContext_*.xml</param-value> </init-param> <!-- tomcat一启动就初始化此Servlet 数字:如果tomcat启动的时候要初始化多个Servlet,它是按照数字的大小来的, 小的先启动,大的后启动 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <!-- *.html(扩展名随便写) 给人的感觉到是html,静态页面,加载特别快; seo:(搜索引擎喜欢静态页面) *.do:是Struts1玩的 *.action:Struts2玩的 *.jsp:javaee有的 --> <url-pattern>*.html</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app> |
-
- 访问:
启动后如下图:
-
- 创建一个Controller--Servlet
- Xml配置
- 创建一个Controller--Servlet
Java文件:Controller:
package com.calrinfo.springmvc.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; /** * XML版本的Controller * @author wangshMac */ public class XMLController implements Controller { /** * 谁调用了此方法 * Spring框架调用的 * Service方法也是Tomcat调用的 * * Tomcat调用了Servlet(Spring的DispatcherServlet-->自己写的类), * 只要有Request和Response就可以工作了 * * ModelAndView:模型和视图 */ @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println(request + "======" + response); /* 赶紧跳转jsp * 服务器端跳转 * 客户端跳转 * */ ModelAndView modelAndView = new ModelAndView() ; /** * 参数是JSP的路径 * 服务器端跳转 */ modelAndView.setViewName("/WEB-INF/jsp/xmlController.jsp"); return modelAndView; } } |
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入Schema 为什么要引入schema或者dtd 因为引入了就有提示了 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" default-autowire="byName"> <!-- 自动按照名字装配 --> <!-- 一定要加上此配置,否则注解不起作用 --> <context:component-scan base-package="com"/>
<!-- name:就是url的访问路径; http://localhost:8080/项目名/bean的name 一定要注意,扩展名和servlet中urlpattern配置的名字一样 --> <bean id="xmlController" name="/xmlController.html" class="com.calrinfo.springmvc.controller.XMLController"></bean> </beans> |
-
-
- 注解版本
-
Java代码:Controller
package com.calrinfo.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * 注解不用写名字, * 写了也木有人调用 * @author wangshMac * */ @Controller public class AnnoController { /** * 随便定义一个方法 * * http://localhost:8080/项目名/类上面的requestMapping+方法上面的requestMapping; * @RequestMapping:后面不加扩展名,不加,系统会自动的加上去 * @return */ @RequestMapping("/hw") public String hw() { System.out.println("==AnnoController==hw="); /* * 默认就是服务器端跳转 * */ return "/WEB-INF/jsp/xmlController.jsp" ; } @RequestMapping("/test") public String test() { System.out.println("==AnnoController==test="); /* * 默认就是服务器端跳转 * */ return "/WEB-INF/jsp/xmlController.jsp" ; } } |
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入Schema 为什么要引入schema或者dtd 因为引入了就有提示了 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" default-autowire="byName"> <!-- 自动按照名字装配 --> <!-- 一定要加上此配置,否则注解不起作用 --> <context:component-scan base-package="com"/>
<!-- name:就是url的访问路径; http://localhost:8080/项目名/bean的name 一定要注意,扩展名和servlet中urlpattern配置的名字一样 --> <bean id="xmlController" name="/xmlController.html" class="com.calrinfo.springmvc.controller.XMLController"></bean> </beans> |
使用注解多好,为啥还要讲xml;
先有的xml后有注解,xml功能最全;
注解就是封装了xml;
适配器,处理器
-
- 标准配置
Web.xml中的/和/*
标准化的springmvc中的前缀和后缀
注解Controller中的return:返回值:客户端跳转和服务器端跳转;
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" version="3.1"> <display-name>springmvc-02-config</display-name> <!-- 只能写servlet,filter,listener --> <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 初始化参数 此参数只能是此Servlet使用 context-param:所有的Servlet都能使用 --> <init-param> <!-- contextConfigLocation:上下文的配置位置 Spring配置文件的路径: 从哪些地方加载Spring的配置文件 --> <param-name>contextConfigLocation</param-name> <!-- 从classpath中找配置文件 第一个*:表示从所有的classpath中找配置文件(包含jar包里面的) 第二个*:通配 --> <param-value>classpath*:applicationContext_*.xml</param-value> </init-param> <!-- tomcat一启动就初始化此Servlet 数字:如果tomcat启动的时候要初始化多个Servlet,它是按照数字的大小来的, 小的先启动,大的后启动 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <!-- /:如果直接访问css,html,js(静态资源文件),是不可以的;jsp和Controller是可以的, /*:都会访问SpringMVC,但是在从Controller跳转到JSP的时候都不行,直接访问静态资源文件都不可以 静态资源文件,如果想可以,得需要配置; 个人建议:使用*.html(扩展名) --> <url-pattern>*.html</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app> |
配置文件
<?xml version="1.0" encoding="UTF-8"?> <!-- 引入Schema 为什么要引入schema或者dtd 因为引入了就有提示了 --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd" default-autowire="byName"> <!-- 自动按照名字装配 --> <!-- 一定要加上此配置,否则注解不起作用 --> <context:component-scan base-package="com"/>
<!-- 让静态资源文件可以访问 --> <!-- <mvc:default-servlet-handler/> -->
<!-- 需求: 我建议将所有的JSP都放到WEB-INF下面; 把所有的JSP从WEB-INF挪到WebContent根目录里面去 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 为所有服务器跳转,客户端跳转的jsp路径增加上前缀和后缀 --> <!-- 前缀 ,注意/可以多加,但是不能不加--> <property name="prefix" value="/WEB-INF/jsp/"/> <!-- 后缀 --> <property name="suffix" value=".jsp"/> </bean> </beans> |
Controller
package com.calrinfo.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * 目录的Controller * @author wangshMac */ @Controller @RequestMapping("/folder/") public class FolderController { /** * 随便定义一个方法 * * http://localhost:8080/项目名/类上面的requestMapping+方法上面的requestMapping; * @RequestMapping:后面不加扩展名,不加,系统会自动的加上去 * @return */ @RequestMapping("/hw") public String hw() { System.out.println("==FolderController==hw="); /* * 默认就是服务器端跳转 * * 返回的jsp路径: * InternalResourceViewResolver的前缀+方法的返回值+后缀 * 如果return null,默认就是类上面的requestmapping+方法上面的requestMapping * */ return "xmlController" ; /*return null ; */ /*return "" ; */ } @RequestMapping("/folder_01") public String folder_01() { System.out.println("==FolderController==folder_01="); /* 默认是服务器端跳转到jsp */ /*return "folder_01" ; */ /* 默认前面加了一个forward;得把路径写全了*/ /*return "forward:/WEB-INF/jsp/folder_01.jsp" ; */ /* 服务器端跳转到另外一个Controller方法; * 扩展名不能省略 */ /*return "forward:/folder/hw.html" ;*/ /* 客户端跳转到另外一个Controller中的方法 */ /*return "redirect:/folder/hw.html" ;*/ /* 客户端跳转的时候,url会发现变化,跳转到任何网址 */ return "redirect:http://www.baidu.com" ; } } |
-
- 驱动分以下三块-*******************************
- url赋值
Java代码:
package com.carlinfo.springmvc.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; /** * url赋值 * @author wangshMac */ @Controller @RequestMapping("/url/") public class UrlController { /** * url赋值 * * @PathVariable:此值为方法参数,从url中获取;在requestMapping定义的时候,用{变量名},变量名 * 必须是方法的参数,两者一样 * ~接收参数的时候全部是字符串,(接收参数);转换为各种各样的类型,处理参数 * 凡是400错误,都是处理参数出问题了. * http://localhost:10001/springmvc-03-driver/url/method01_10_a.html * 在url中对应的requestMapping;一定要对应上去,把requstmapping中的{};在url中理解为任何字符 * * 原:http://localhost:10001/springmvc-03-driver/url/usersInfo.html?id=10 * 目标:http://localhost:10001/springmvc-03-driver/url/10.html * * https://item.jd.com/goodsInfo.html?id=4325123 * https://item.jd.com/4325123.html * https://item.jd.com/5001175.html * 把?后面的参数挪到?的前面;urlRewrite; * REST:有含义的url; * SEO喜欢;?左边的是url,?后面的都不认识;将原来的一个url变成了多个url,让SEO多收录一些; * @return */ @RequestMapping("/method01_{id}_{age}") public String method01(@PathVariable String id,@PathVariable int age) { System.out.println("=UrlController===method01="); System.out.println("==id==" + id); System.out.println("==age==" + age); return "method01" ; } } |
- 基本数据类型赋值字符串
- 对象赋值
Java代码:
package com.carlinfo.springmvc.controller; import java.util.Arrays; import java.util.List; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.carlinfo.springmvc.pojo.AAdmins; /** * 表单操作 * @author wangshMac * */ @Controller @RequestMapping("/form/") public class FormController { /** * 表单打开 *springmvc-03-driver/form/formInsert.html?name=a&age=20&score=30.2 *name=a&age=20&score=30.2:表单提交的参数(get,post) *省去了自动接收参数, *自动处理参数; *如果参数的类型是非String,千万不要发生类型转换的错误问题 *参数的名字要类请求参数中键值对 键的名字一样 * *页面打开的时候,就传值(get方式) * @return */ @RequestMapping("/formInsert") public String formInsert(String name,int age , double score) { System.out.println("===FormController====formInsert="); System.out.println("==name==" + name); System.out.println("==age==" + age); System.out.println("==score==" + score); return "formInsert" ; } /** * 表单打开提交 * * (是表单提交的时候传值)post方式; * post和get:post提交:只能是表单提交,而且method=post,其它的全部是get提交 * * ~自动接收参数 * ~自动处理参数 * ~自动的new对象 * ~自动的为对象赋值 * * ~不足:为啥不能将方法中的参数放到四大作用域中 * * ~对象的属性名得和参数键值对中键的名字一样,键的名字在表单提交时就是控制的name属性 * 如果请求中有多个键,值是字符串,用逗号隔开; * 数组接口,可以,List接口不行 * Map:虽然不报错,但是也不是我们想要的; * @return */ @RequestMapping("/formInsertSubmit") public String formInsertSubmit(String name,int age , double score, byte sex,int cityId, //String hobbys, //String[] hobbys, //List hobbys, Map<String, String> hobbys, AAdmins admins) { System.out.println("===FormController====formInsertSubmit="); System.out.println("==name==" + name); System.out.println("==age==" + age); System.out.println("==score==" + score); System.out.println("==admins==" + admins); System.out.println("==sex==" + sex); System.out.println("==cityId==" + cityId); //System.out.println("==hobbys==" + Arrays.toString(hobbys)); System.out.println("==hobbys==" + hobbys); return "formInsert" ; } } |
AAdmins的POJO
package com.carlinfo.springmvc.pojo; /** * 管理员的POJO * * @author wangshMac * */ public class AAdmins { private String name; private int age; private double score; Set/get方法 @Override public String toString() { return "AAdmins [name=" + name + ", age=" + age + ", score=" + score + "]"; } } |
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> <form action="${pageContext.request.contextPath }/form/formInsertSubmit.html" method="post"> <input type="hidden" name="id" value="1"> <table border="1"> <tr> <td>邮箱:</td> <td><input type="text" name="name" value="22@22.com"></td> </tr> <tr> <td>年龄:</td> <td><input type="text" name="age" value="10"></td> </tr> <tr> <td>分数:</td> <td><input type="text" name="score" value="10.2"></td> </tr> <tr> <td>性别:</td> <td> <label for="sex0"> <input type="radio" name="sex" value="0" id="sex0">男 </label> <label for="sex1"> <input type="radio" name="sex" value="1" id="sex1">女 </label> </td> </tr> <tr> <td>城市</td> <td> <select name="cityId"> <option value="0">北京</option> <option value="1">郑州</option> <option value="2">朱仙傎</option> </select> </td> </tr> <tr> <td>爱好:</td> <td> <label for="hobbys0"> <input type="checkbox" name="hobbys" value="0" id="hobbys0">逃课 </label> <label for="hobbys1"> <input type="checkbox" name="hobbys" value="1" id="hobbys1">玩 </label> <label for="hobbys2"> <input type="checkbox" name="hobbys" value="2" id="hobbys2">谈恋爱 </label> </td> </tr> <tr> <td>个性签名:</td> <td> <textarea rows="5" cols="50" name="intro">adfasfasfasf</textarea> </td> </tr> <tr> <td colspan="2"><input type="submit" value="提交"></td> </tr> </table> </form> 从四大作用域中取值 name:${name }<br/> </body> </html |