入门程序
11. 创建maven项目需要选择webapp骨架(org.apache.maven.archetypes:maven-archetype-webapp),还有添加额外配置(archetypeCatalog internal),防止创建maven的web项目慢的问题。
22. 引入依赖(修改maven的jdk编译环境为1.8)
3 spring-context
4 spring-web
5 spring-webmvc
6 servlet-api(scope--->provide)
7 jsp-api(scope--->provide)
8 3. 核心配置文件的配置(mvc和context约束)
9 1. 开启注解扫描 <context:component-scan base-package />
10 2. 视图解析器对象 <bean class="InternalResourceViewResolver"> 拼接字符串的前面 和 拼接字符串的后面的两个set </bean>
11 3. 开启SpringMVC框架注解支持 <mvc:annotation-driven/>
124. web.xml的配置
13 1. 配置前端控制器,加载核心配置文件
14 <servlet>
15 <servlet-name>dispatcherServlet</servlet-name>
16 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
17 <init-param>
18 <param-name>contextConfigLocation</param-name>
19 <param-value>classpath:springmvc.xml</param-value>
20 </init-param>
21 <load-on-startup>1</load-on-startup>
22 </servlet>
23 <servlet-mapping>
24 <servlet-name>dispatcherServlet</servlet-name>
25 <url-pattern>/</url-pattern>
26 </servlet-mapping>
275. 编写Controller和jsp页面进行测试
28 1. 使用@Controller注解和jsp配置视图解析器进行测试
29 2. 使用@RestController进行测试(推荐,相对简单)
MVC的执行流程
11. 配置文件的加载:
2 启动项目,加载web.xml文件
3 创建Servlet(前端/核心控制器-->指挥中心)的对象
4 springmvc.xml的加载
5 注解扫描加载SpringIOC的bean(@Controller)
6 视图解析器
7 SpringMVC注解支持(@RequestMapping)
82. 请求响应:
9 客户端发送请求------> 核心控制器(进入SpringMVC的请求流程)----->
10 调用HandlerMapping(处理器映射器),匹配被@Controller注解注解的类中的@RequestMapping ----->
11 调用HandlerAdapter(处理器适配器)执行handle(Controller中声明的方法),handle返回结果(ModelAndView,模型视图,封装结果和视图)给HandlerAdapter ------->
12 HandlerAdapter返回MOdelAndView给核心控制器,核心控制器拿到结果去找视图解析器(ViewResolver)进行视图解析----->
13 视图解析器进行物理拼接形成具体的路径(View),返回给核心控制器 ------>
14 核心控制器进行视图渲染,填充数据到reuqest域中,response响应返回给客户端
153. 组件介绍
16 前端/核心控制器: 中央调度,协调作用
17 处理器映射器(HanderMapping): 根据请求的url查找Handler
18 处理器适配器(HanderAdapter): 执行Handle
19 ModelAndView: 模型及视图,封装结果视图
20 ViewResolver: 视图解析器,解析逻辑视图
21 Handle: 程序员编写业务逻辑处理,也就是Controller的方法
请求参数绑定
11. 基本数据类型绑定:
2 原则: 请求后拼接的参数与handle的参数名保持一致
32. JavaBean对象的绑定
4 1. 简单Bean直接使用form表单,name属性的值为Bean对象的属性名
5 2. Bean内包含另一个Bean,name的值使用属性.属性的方式
6 3. list使用属性下标点属性 ------> list[0].name
7 4. map使用属性key属性的方式 -----> list['one'].name
8
93. 中文乱码问题:
10 post乱码可以在web.xml中配置Spring提供的CharacterEncodingFilter
11 get乱码:
12 tomcat8之前,在tomcat的配置文件中配置URIEncoding="utf-8"
13 new String(username.getBytes("ios-8859-1"),"UTF-8")的方式
14
154. 日期类型转换:
16 1. 自定义类实现Converter<S,T>接口,使用DateFormat进行格式的转换.
17 2. 在springmvc中配置自定义转换器(ConversionServiceFactoryBean).
18 * 注意是context包下的转换器
19 * 配置converters属性
20 * 注入自定义转换器的bean
SpringMVC使用原生的Servlet
Handler方法的形参设置HttpServletRequest和HttpServletResponse就可以获取到所有的原生Servlet对象了
注解介绍
11. @RequestMapping:
2 * 作用位置:
3 1. 类上: 窄化请求路径,业务隔离
4 2. 方法上: url请求映射
5 * 属性:
6 1. value: 指定请求路径,与path属性一样
7 2. method: 指定请求方式,值有GET,POST,DELETE等等(枚举类型,RequestMethod)
8 3. params: 用于指定限制请求参数条件
9 4. headers: 用于指定请求头
10
112. @RequestParam:
12 * 作用 : 在页面传递的参数名与后台不一致的时候需要使用该注解,作用于参数之前
13 * 属性 :
14 1. name/value : 指定页面传递的参数名
15 2. required : 是否为必须,默认为true,表示该参数必须传递
16 3. defaultValue : 给定参数一个默认值,当有默认值的时候required属性感觉就无效了
17
183. @RequestBody
19 * 作用: 用于获取请求体的内容.(get请求不适用,POST请求适用)
20
214. @PathVariable(基于Restful风格的url支持)
22 * 作用在参数之前,目的是获取请求url中的占位符(参数)的信息
23 /test/{sid} ----> 请求路径
24 @PathVaribale(name="sid") Integer id ---> 方法的参数
25 /test/10 ----> 客户端的访问路径
26 * Restful的理解:
27 通过请求参数决定对哪个资源进行操作
28 通过请求方式决定采用何种操作(post,delete,put,get)
29
305. HiddenHttpMethodFilter:
31 浏览器的form表单只支持get和post请求,要洗那个发送put或delete请求,需要借助SpringMVC提供的HiddenHttpMethodFilter.
32 使用:
33 1. 在web中配置HiddenHttpMethodFilter过滤器
34 2. 在表单中添加隐藏域,<input type="hidden" name="_method" value="PUT"/>
35 3. 定义handle,声明method为RequestMethod.PUT
36
376. @RequestHeader
38 用于获取请求消息头,作用在方法参数之前
39 value属性可以指定获取哪个请求头信息(User-Agent比较常用)
40
417. @CookieValue
42 * 获取指定名称cookie的值
43 * value属性指定cookie名称(JSESSIONID)
44
458. @ModelAttribute
46 * 作用位置:
47 1. 方法上: 被@ModelAttribute注解修饰的方法表示该方法会在当前Controller的人格一个方法执行前先执行
48 应用在表单提交实体数据不完整的情况下,为实体数据添加内容.
49 方法有返回值(直接返回user),springmvc会将方法执行的返回值,存放在Model对象,最终会存放在Request中:
50 考虑在修改的时候根据id获取实体,方法返回实体,前台只需要传递修改的内容就可以了.
51 方法无返回值,springmvc会将方法形参中的map中的数据存放在Model对象,最终会存放在Request中:
52 在方法中使用map保存数据,在Handler的参数前使用@ModelAttribute(name="key")获取
53 2. 形式参数前(需制定value(key)属性):
54 获取request中获取对应的value的数据
55
569. @SessionAttributes(只能作用于类上,指定属性)
57 * 用于多个Handler间的参数共享(将数据存放在session域)
58 * 使用Model对象的addAttribute方法存放数据
59 * 使用ModelMap对象的get方法来获取session数据
60 * 使用setComplete()方法清空session域的数据(使用的是SessionStatus对象)
Handler返回值类型
11. 字符串:简单字符串是逻辑视图名称
2 * 使用返回的字符串,经过视图解析器,拼接前缀后缀,跳转到真实路径
32. void ===> 原始的Servlet操作
4 * 请求路径默认是: 前缀 + handle访问路径 + 后缀
5 * 使用原生Servlet进行跳转和携带参数,但是注意这个时候不会执行ViewResolver,所以必须写全路径,这个需要注意.在handle最后加个return;防止handle跳转方法完成后继续执行后续的代码.
6 * 还有需要注意重定向是无法访问WEB-INF目录下的东西.
7 * 直接响应数据: response.getWriter().print("content");注意处理乱码问题
83. ModelAndView
9 * ModelAndView对象: ModelAndView mv = new ModelAndView();
10 * 可以存放数据到对象,使用mv.addObject("key","value");实际还是存放在Model中,最后还是request域中
11 * 存放跳转的页面: 使用mv.setViewName("success");
124. forward和redirect关键字的用法(返回类型还是String):
13 * 返回的写法不一样,有了forward关键字后就不能调用视图解析器.
14 return "forward:/WEB-INF/pages/success.jsp"
15 * return "redirect:/index.jsp"; 重定向不能直接跳转到WEB-INF的目录下,并且redirect关键字不用添加项目目录
16 * return "forward:testString"; 转发到指定的的Handle
17 return "redirect:/user/testString";重定向到指定的的Handle
响应JSON数据
11. 在springmvc配置文件中配置静态资源不拦截(因为前端控制器会拦截所有资源):
2 <mvc:resources mapping="/js/**" location="/js/" />,表示js文件下面的所有文件都不拦截
3 <mvc:resources mapping="/css/**" location="/css/" />
4 <mvc:resources mapping="/images/**" location="/images/" />
5 > 注意静态资源放在web-app下
6
7 上面的配置在mapping的后面也一定要加**,否则会失败(在我电脑上是这样),如果还是失败,可以试试在web.xml中配置:
8 <servlet-mapping>
9 <servlet-name>default</servlet-name>
10 <url-pattern>*.js</url-pattern>
11 </servlet-mapping>
12
132. ajax请求返回json数据:
14 * $.ajax({
15 url:"user/testAjax",
16 type:"POST",
17 contentType:"application/json;charset=utf-8",
18 data:'{"username":"hehe","password":"123456","age":24}',
19 dataType:"json",
20 success:function(data){
21 alert(data);
22 }
23
24 })
253. 自动转换,将json字符串转换为对象,需要额外依赖jackson的jar包:
26 <dependency>
27 <groupId>com.fasterxml.jackson.core</groupId>
28 <artifactId>jackson-databind</artifactId>
29 <version>2.9.7</version>
30 </dependency>
31 <dependency>
32 <groupId>com.fasterxml.jackson.core</groupId>
33 <artifactId>jackson-core</artifactId>
34 <version>2.9.7</version>
35 </dependency>
36 <dependency>
37 <groupId>com.fasterxml.jackson.core</groupId>
38 <artifactId>jackson-annotations</artifactId>
39 <version>2.9.7</version>
40 </dependency>
41
42 接收json数据需要使用 ==@RequestBody==
43 获取请求中的数据
44 如果请求的参数是json格式,使用pojo接受,但是注意参数名和实体属性名一致
45
46 响应json数据需要使用 ==@ResponseBody==
47 直接将方法执行的返回值响应给客户端
48 如果是pojo,将pojo对象转化为json字符串
传统方式文件上传(了解):
11. 表单的enctype属性取值必须是: multipart/form-data
2 method属性值必须是post
3 提供你文件选择域: <input type="file" />
42. 三方组件实现,引入额外依赖:
5 commons-fileupload
6 commons-io
73. 传统方式文件上传(后台代码实现):
8 创建文件的上传路径(path),使用request.getSession().getServletContext().getRealPath("/uploads");
9 核心解析器:
10 DiskFileItemFactory ---> 磁盘文件的工厂对象
11 ServletFileUpload ---> 文件上传的核心解析器,传入工厂对象
12 解析request对象
13 List<FileItem> list = ServletFileUpload.parseRequest(request);
14 文件上传:
15 遍历list,判断是否为普通表单项(isFormFiled),不是则进行上传
16 获取文件上传名,修改上传名为唯一上传名(考虑使用UUID或者日期)
17 fileItem.write(new File(path,filename));path表示父级目录,filename表示修改后的文件名.
18 最后使用fileItem.delete(); 用来删除临时文件
19
20 2223
24 @RequestMapping("/fileupload1")
25 public String fileuoload1(HttpServletRequest request) throws Exception {
26 System.out.println("文件上传...");
27
28 // 使用fileupload组件完成文件上传
29 // 上传的位置
30 String path = request.getSession().getServletContext().getRealPath("/uploads/");
31 // 判断,该路径是否存在
32 File file = new File(path);
33 if(!file.exists()){
34 // 创建该文件夹
35 file.mkdirs();
36 }
37
38 // 解析request对象,获取上传文件项
39 DiskFileItemFactory factory = new DiskFileItemFactory();
40 ServletFileUpload upload = new ServletFileUpload(factory);
41 // 解析request
42 List<FileItem> items = upload.parseRequest(request);
43 // 遍历
44 for(FileItem item:items){
45 // 进行判断,当前item对象是否是上传文件项
46 if(item.isFormField()){
47 // 说明普通表单向
48 }else{
49 // 说明上传文件项
50 // 获取上传文件的名称
51 String filename = item.getName();
52 // 把文件的名称设置唯一值,uuid
53 String uuid = UUID.randomUUID().toString().replace("-", "");
54 filename = uuid+"_"+filename;
55 // 完成文件上传
56 item.write(new File(path,filename));
57 // 删除临时文件
58 item.delete();
59 }
60 }
61
62 return "success";
63 }
SpringMVC的文件上传(掌握)
11. springmvc.xml配置文件上传解析器:
2 类为CommonsMultipartResolver
3 id为multipartResolver,这个不能改变(这个很重要)
4 属性为:maxUploadSize,值为10485760
5 <!--配置文件上传解析器-->
6 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
7 <property name="maxUploadSize" value="10485760"/>
8 </bean>
9
102. handler的形参: (HttpServletRequest request,MultipartFile upload)
11 表单的隐藏域的name属性必须和handler的形参MultipartFile的对象的名字一样.
12 <form action="/file/fileupload" method="post" enctype="multipart/form-data">
13 文件上传:<input type="file" name="upload">
14 <input type="submit" value="提交">
15 </form>
163. handler的步骤:
17 1. 创建文件上传目录path
18 2. 获取文件名,修改文件名为唯一名字
19 3. 使用upload.transferTo(new File(newFileName))就完成了
20
21 @RequestMapping("fileupload")
22 public String fileUpload(HttpServletRequest request, MultipartFile upload) throws Exception {
23 // 创建文件上传目录
24 String realPath = request.getSession().getServletContext().getRealPath("/uploads/");
25 // 创建File
26 File file = new File(realPath);
27 // 判断目录是否存在
28 if(!file.exists()){
29 // 创建该文件夹
30 file.mkdirs();
31 }
32 // 获取文件名,并修改文件名为唯一
33 String name = upload.getOriginalFilename();
34 // 生成uuid
35 String replace = UUID.randomUUID().toString().replace("-", "");
36 // 唯一文件名
37 String fileName = replace + "_" + name;
38 // 拼接最后的路径
39 String newPath = realPath + fileName;
40
41 // 进行文件的上传
42 upload.transferTo(new File(newPath));
43
44
45 return "hello";
46 }
SpringMVC跨服务器方式的文件上传
11. 搭建图片服务器
2 1. 修改tomcat端口号(修改3个地方)
3 2. 修改tomcat的conf下的web.xml,修改readonly属性为false
4 3. 在webapps下新建uploads目录
52. 加入依赖:
6 jersey-core
7 jersey-client
83. 步骤:
9 创建客户端的对象Client.create()
10 和图片服务器建立连接(client.resource())
11 上传文件(webResource.put(new File(newFileName)))
12
13 @RequestMapping("/fileupload3")
14 public String fileuoload3(MultipartFile upload) throws Exception {
15 System.out.println("跨服务器文件上传...");
16
17 // 定义上传文件服务器路径
18 String path = "http://localhost:9090/uploads/";
19
20 // 说明上传文件项
21 // 获取上传文件的名称
22 String filename = upload.getOriginalFilename();
23 // 把文件的名称设置唯一值,uuid
24 String uuid = UUID.randomUUID().toString().replace("-", "");
25 filename = uuid+"_"+filename;
26
27 // 创建客户端的对象
28 Client client = Client.create();
29
30 // 和图片服务器进行连接
31 WebResource webResource = client.resource(path + filename);
32
33 // 上传文件
34 webResource.put(upload.getBytes());
35
36 return "success";
37 }
SpringMVC的异常处理
11. 不处理异常造成的问题:
2 * 用户体验差
3 * 系统安全性容易出现问题
42. 处理:
5 1. 编写自定义异常处理类,继承Exception
6 public class MyException extends Exception {
7 private String msg;
8 public MyException(String msg) {
9 this.msg = msg;
10 }
11 public String getMsg() {
12 return msg;
13 }
14 public void setMsg(String msg) {
15 this.msg = msg;
16 }
17 }
18 2. 编写异常处理器,实现HandlerExceptionResolver
19 public class MyExceptionResolver implements HandlerExceptionResolver {
20 @Override
21 public ModelAndView resolveException(HttpServletRequest httpServletRequest,
22 HttpServletResponse httpServletResponse,
23 Object o,
24 Exception e) {
25 // 创建自定义异常类
26 MyException myException = null;
27 // 转换
28 if(e instanceof MyException){
29 myException = (MyException)e;
30 } else{
31 myException = new MyException("程序遇到错误,但不是自定义异常类");
32 }
33 // 创建ModelAndView
34 ModelAndView mv = new ModelAndView();
35 mv.addObject("errormsg",myException.getMsg());
36 mv.setViewName("error");
37 return mv;
38 }
39 }
40 3. 配置异常处理器,SpringMVC中配置异常处理器(也就是声明Bean)
41 <!--配置异常处理器 -->
42 <bean id="myExceptionResolver" class="com.itheima.exception.MyExceptionResolver"></bean>
43 4. Controller如何进行编写呢?
44 @RequestMapping("exce")
45 public String testException() throws MyException {
46 try {
47 int i = 1 / 0;
48 } catch (Exception e) {
49 e.printStackTrace();
50 throw new MyException("程序错误");
51 }
52 return "hello";
53 }
SpringMVC的拦截器
11. 拦截器: 对处理器进行预处理和后处理(AOP的思想)
22. 拦截器链: 多个拦截器按一个次序形成一个链,执行顺序考虑栈的结构,前置代码是入栈,后置代码是出栈
33. 过滤器(filter)与拦截器(interceptor):
4 过滤器什么都可以拦截,并且是属于servlet的,任何项目都可以用
5 拦截器属于SpringMVC的,只有在SpringMVC的项目中使用,并且只能拦截控制器的访问
64. 使用拦截器的步骤:
7 1. 编写拦截器: 类实现HandlerInterceptor,实现3个方法:
8 boolean preHandler(): 预处理,handler执行前执行
9 true: 放行,如果有多个拦截器,放行到下一个拦截器,没有后续拦截器,执行Handler方法
10 false: 不放行, 到此为止,不继续向下执行
11 postHandler(): 后处理,handler之后,跳转页面之前执行
12 afterComletion(): 最后执行的方法,也就是成功返回页面后执行的代码
13
14 public class MyInterceptor implements HandlerInterceptor {
15 171819202122
23 @Override
24 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
25 System.out.println("preHandle=======================");
26 return true;
27 }
28
29 313233343536
37 @Override
38 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
39 System.out.println("postHandle=======================");
40 }
41
42 444546474849
50 @Override
51 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
52 System.out.println("afterCompletion=============================");
53 }
54 }
55 2. 配置拦截器:
56 <mvc:interceptors>
57 <!--可以配置对个interceptor,表示多个拦截器-->
58 <mvc:interceptor>
59 <!--拦截的具体方法-->
60 <mvc:mapping path="/**"/> <!--所有的方法都拦截-->
61 <!--不要拦截的具体方法,和上面那个配置一个就好-->
62 <!-- <mvc:exclude-mapping path=""/>-->
63 <!--配置拦截器对象-->
64 <bean class=""/>
65 </mvc:interceptor>
66
67 </mvc:interceptors>
68
69
70 <!--配置拦截器-->
71 <mvc:interceptors>
72 <mvc:interceptor>
73 <mvc:mapping path="/**"/>
74 <bean class="com.itheima.interceptor.MyInterceptor"/>
75 </mvc:interceptor>
76 </mvc:interceptors>
77
78
79 3. 前端:
80 <% System.out.println("hello.jsp================"); %>
81
82 执行效果:
83 preHandle=======================
84 interceptor===================
85 postHandle=======================
86 hello.jsp================
87 afterCompletion=============================
885. 拦截器的作用:
89 登录拦截器=======> 在prehandler()方法中获取session,判断有无用户,无用户跳转到登录.