1.什么是SpringMVC?
SpringMVC是web层的mvc开发框架,是属于Spring 框架的WEB模块中的一个部分。
2.SpringMVC的执行流程
- 启动服务器的时候配置在web.xml文件中的中央控制器【DispatcherServlet】被初始化完成,并且加载配置的springMVC的配置文件。
- 客户端浏览器发送http请求。
- http请求被中央控制器【DispatcherServlet】拦截,转交给url解析器解析。
- Url解析器解析http请求,得到具体的请求路径。
- Url解析器将解析得到的具体的请求路径返回给中央控制器【DispatcherServlet】。
- 中央控制器【DispatcherServlet】将得到的具体的请求路径转交给控制器适配器。
- 控制器适配器根据具体的请求路径查找与之对应的请求处理类。
- 请求处理类就执行具体的请求处理,得到ModelAndView对象【1.数据。2.跳转地址】,将ModelAndView对象交给控制器适配器,控制器适配器将ModelAndView对象返回给中央控制器【DispatcherServlet】。
- 中央控制器【DispatcherServlet】将ModelAndView对象转交给视图解析器去解析。
- 视图解析器解析ModelAndView对象,得到一个具体的数据显示路径,将这个具体的数据显示路径返回给中央控制器【DispatcherServlet】。
- 中央控制器【DispatcherServlet】得到具体的数据显示路径之后,将路径所代表的资源转换执行成一个html数据。
将转换执行后的html数据返回给客户端浏览器。
3.请求的访问路径配置
- web.xml文件中DispatcherServlet配置的<url-pattern>
1.1 <url-pattern>/</url-pattern>
对应 http://127.0.0.1:8080/springmvc1/add
1.2 <url-pattern>*.do</url-pattern>
对应 http://127.0.0.1:8080/springmvc1/add.do
1.3 <url-pattern>/*</url-pattern> 这是一个错误的方式
2.springmvc配置文件中的控制器的name属性值
控制器的name属性值设置要与web.xml文件中DispatcherServlet配置的<url-pattern>
的配置形式一致
2.1.web.xml文件中DispatcherServlet配置的<url-pattern>/</url-pattern>那么springmvc配置文件中的控制器的name属性值应该为“/xxxx”
2.2 web.xml文件中DispatcherServlet配置的<url-pattern>*.do</url-pattern>那么springmvc配置文件中的控制器的name属性值应该为“/xxxx.do”
以后控制器的name属性值会被@RequestMapper注解的value属性代替
4.ModelAndView类、
1.请求处理方法的返回值是ModelAndView类
2.组成ModelAndView类的第一部分是一个Model【模型】封装数据
第二部分是一个View【视图】展示数据的页面元素
3.ModelAndView类是用来封装数据,展示数据的页面元素。
4.构造方法ModelAndView()来创建ModelAndView类的对象
ModelAndView mav=new ModelAndView();
5.封装数据的方法addObject(attributeName, attributeValue)相当于setAttribute(key,value)
mav.addObject("username","zhangsan");
6.设置展示数据的页面元素的名称setViewName(viewName)
mav.setViewName("test");
mav.setViewName("test.jsp");
mav.setViewName("test.html");
mav.setViewName("控制器对应的请求处理路径");
mav.setViewName("test");---forword跳转[转发]
mav.setViewName("forward:test.jsp");
mav.setViewName("redirect:test.jsp");----sendRedirect跳转[重定向]
5.视图解析器
InternalResourceViewResolver------解析展示数据的页面元素
<!-- 视图解析器 -->
<!-- 利用请求处理类中的得到的视图名,通过视图解析器的前缀和后缀合并得到一个完整的页面元素的访问路径。 -->
<!-- prefix+视图名称+suffix : 完整的页面元素的访问路径 -->
<!-- prefix==http://localhost:8080/demo1/ -->
<!-- 视图名称:ModelAndView中setViewName("test")的参数test -->
<!-- suffix:后缀[.jsp] -->
<!-- http://localhost:8080/demo1/test.jsp -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=""></property>
</bean>
6.DispatcherServlet中央处理器设置加载SpringMVC配置文件的设置
我们在启动程序的时候需要加载SpringMVC配置文件,此时这个SpringMVC配置文件的位置可能有所不同,SpringMVC配置文件在不同的位置是DispatcherServlet中央处理器如何配置SpringMVC配置文件的位置。
1.通过init-param元素配置加载SpringMVC配置文件
2.SpringMVC配置文件在src/main/resources文件夹下的时候:
src/main/resources----->springmvcconfig.xml
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvcconfig.xml</param-value>
</init-param>
3.SpringMVC配置文件在WEB-INF文件夹下的时候:
src/main/webapp/WEB-INF----->springmvcconfig.xml
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myspringmvc.xml</param-value>
</init-param>
4.如果我们不在web.xml文件中配置init-param元素配置加载SpringMVC配置文件
- 将SpringMVC配置文件放放置在WEB-INF文件夹下
- SpringMVC配置文件,名称“<servlet-name>-servlet.xml”
例如:myspringmvc-servlet.xml
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<servlet>
SpringMVC配置文件
src/main/webapp/WEB-INF-------[springmvc-servlet.xml]
注意:通常情况下我们把SpringMVC配置文件/资源文件【jsp/html】放置在WEB-INF文件夹
7.@Controller/@RequestMapping/@Service/@RestController/@Component/@Autowired/
@Resource/@RequestBody/@ResponseBody
1.@Controller:放在一个类的上面,表示这个类是控制器类 开启注解:<context:component-scan base-package="com"/>
2.@RestController:放在一个类的上面,表示这个类是控制器类。@Controller与@RestController的区别 @RestController不用加@ResponseBody注解可自动返回join数据
3.@RequestMapping: 是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径.属性:
value: 指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);
method: 指定请求的method类型, GET、POST、PUT、DELETE等;
4.@Service: 此注解属于业务逻辑层,默认按照名称进行装配,如果名称可以通过name属性指定,如果没有name属性,注解写在字段上时,默认去字段名进行查找,如果注解写在setter方法上,默认按照方法属性名称进行装配。当找不到匹配的bean时,才按照类型进行装配,如果name名称一旦指定就会按照名称进行装配
@Repository持久层:此注解式持久层组件,用于标注数据访问组件,即DAO组件
DAO层
先定义一个接口
<span style="color:#000000"><code class="language-java" style="margin-left:0px"><span style="color:#b294bb">public</span> <span style="color:#b294bb">interface</span> IIocDao<span style="color:#999999">{</span>
<span style="color:#b294bb">public</span> <span style="color:#b294bb">void</span> <span style="color:#81a2be">add</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
</code></span>
然后实现类
<span style="color:#000000"><code class="language-java" style="margin-left:0px"><span style="color:#969896"><em>//Dao层中定义了一些接口</em></span>
<span style="color:#969896"><em>//表示将Dao类声明为bean</em></span>
<span style="color:#999999">@Repository</span>
<span style="color:#b294bb">public</span> <span style="color:#b294bb">class</span> IocDao <span style="color:#b294bb">implements</span> IIocDao<span style="color:#999999">{</span>
<span style="color:#b294bb">public</span> <span style="color:#b294bb">void</span> <span style="color:#81a2be">add</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>
System<span style="color:#999999">.</span>out<span style="color:#999999">.</span><span style="color:#81a2be">println</span><span style="color:#999999">(</span><span style="color:#b5bd68">"调用了Dao"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>
<span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>
另外一种解释: @Repository对应数据访问层Bean
<span style="color:#000000"><code class="language-java" style="margin-left:0px"><span style="color:#999999">@Repository</span><span style="color:#999999">(</span>value<span style="color:#a67f59">=</span><span style="color:#b5bd68">"userDao"</span><span style="color:#999999">)</span>
<span style="color:#b294bb">public</span> <span style="color:#b294bb">class</span> UserDaoImpl <span style="color:#b294bb">extends</span> BeansDaoImpl<span style="color:#81a2be"><span style="color:#999999"><</span>User<span style="color:#999999">></span></span><span style="color:#999999">{</span>
<span style="color:#999999">.</span><span style="color:#999999">.</span><span style="color:#999999">.</span><span style="color:#999999">.</span><span style="color:#999999">.</span><span style="color:#999999">.</span>
<span style="color:#999999">}</span>
</code></span>
@Repository(value=“userDao”)注解告诉Spring ,让Spring创建一个名字叫做"userDao"的UserDapImpl实例。
当Service需要使用Spring创建的名字叫“userDao”的UserDaoImpl实例时,就可以使用@Resource(name=“userDao”)注解告诉Spring,Spring把创建好的userDao注入给Service即可。
<span style="color:#000000"><code class="language-java" style="margin-left:0px"> <span style="color:#969896"><em>//注入userDao,从数据库中根据用户Id取出指定用户时需要用到</em></span>
<span style="color:#999999">@Resource</span><span style="color:#999999">(</span>name <span style="color:#a67f59">=</span> <span style="color:#b5bd68">"userDao"</span><span style="color:#999999">)</span>
<span style="color:#b294bb">private</span> BaseDao<span style="color:#81a2be"><span style="color:#999999"><</span>User<span style="color:#999999">></span></span> userDao<span style="color:#999999">;</span></code></span>
5.@Component注解:@Component 注解的类和自动创建的 bean 之间存在隐式的一对一映射关系。由于只需要声明一个注解,其他过程都是自动化的,所以对 bean 的创建过程可控程度较低。
6.@Autowired/注解:只按照byType注入
Autowired为Spring提供的注解,需要导入包org.springframework.beans.factory.annotation.Autowired。
@Autowired采取的策略为按照类型注入
7.@Resource:@Resource默认按照ByName自动注入。
①如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
②如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常。
③如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配。
区别:
(1)@Autowired与@Resource都可以用来装配bean,都可以写在字段或setter方法上
(2)@Autowired默认按类型装配,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false。如果想使用名称装配可以结合@Qualifier注解进行使用。
(3)@Resource,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行名称查找。如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
推荐使用@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与Spring的耦合。
8.@RequestBody:@RequestBody的作用是将前端传来的json格式的数据转为自己定义好的javabean对象
9.@ResponseBody:的作用是将后端以return
返回的javabean类型数据转为json类型数据。
8.请求处理方法接收请求参数值
http请求:http://localhost:8080/mvc/user/login/zhangsan/123456
请求参数:/zhangsan/123456
1.@PathVariable 定义在方法上获取请求url路径上的参数数据
例如:
package com.click369.springmvc.handler;
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;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping(value="/user")
public class UserHandler {
//处理注册请求的方法
@RequestMapping(value="/register1/{username}/{mypass}",method=RequestMethod.GET)
public ModelAndView registerMethod1(@PathVariable("username")String name,
@PathVariable("mypass")String pass)throws Exception{
System.out.println("name=="+name);
System.out.println("pass=="+pass);
ModelAndView mav=new ModelAndView();
mav.addObject("myname",name);
mav.addObject("mypass",pass);
mav.setViewName("test");
return mav;
}
}
http请求:http://localhost:8080/springmvcdemo1/test/my?name=zhangsan&password=123456
请求参数:name=zhangsan&password=123456
2.@RequestParam 定义在方法上,获取请求中通过key=value方式传递的参数数据
例如:get方式提交请求
//处理注册请求的方法
@RequestMapping(value="/register2",method=RequestMethod.GET)
public ModelAndView registerMethod2(@RequestParam("username")String name,
@RequestParam("password")String pass)throws Exception{
System.out.println("name=="+name);
System.out.println("pass=="+pass);
ModelAndView mav=new ModelAndView();
mav.addObject("myname",name);
mav.addObject("mypass",pass);
mav.setViewName("test");
return mav;
}
post方式提交请求
//处理注册请求的方法
@RequestMapping(value="/register3",method=RequestMethod.POST)
public ModelAndView registerMethod3(@RequestParam("username")String name,
@RequestParam("password")String pass)throws Exception{
System.out.println("name=="+name);
System.out.println("pass=="+pass);
ModelAndView mav=new ModelAndView();
mav.addObject("myname",name);
mav.addObject("mypass",pass);
mav.setViewName("test");
return mav;
}
3.HttpServletRequest对象接收数据
//处理注册请求的方法
@RequestMapping(value="/register4",method=RequestMethod.POST)
public ModelAndView registerMethod4(HttpServletRequest req)throws Exception{
String name=req.getParameter("username");
String pass=req.getParameter("password");
ModelAndView mav=new ModelAndView();
mav.addObject("myname",name);
mav.addObject("mypass",pass);
mav.setViewName("test");
return mav;
}
4.在请求处理方法中定义对应参数的变量,变量的名称与页面元素的name属性值相同
@RequestMapping(value="/register5",method=RequestMethod.POST)
public ModelAndView registerMethod5(String username,String password)throws Exception{
//String name=req.getParameter("username");
//String pass=req.getParameter("password");
ModelAndView mav=new ModelAndView();
mav.addObject("myname",username);
mav.addObject("mypass",password);
mav.setViewName("test");
return mav;
}
9.SpringMVC的文件上传和下载
1.需要使用Apache的commons-fileupload组件【文件上传组件】
2.需要配置一个文件上传的视图解析器CommonsMultipartResolver
3.创建上传页面
表单的提交方式method一定是post
表单中的enctype属性一定是multipart/form-data
表单中的文件上传元素<input type="file" name="file">
4.创建文件上传的控制器
例如:
Pom.xml
<!-- 配置commons-fileupload的依赖 -->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
springmvc.xml
<!-- 上传文件的视图解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="4096" />
<property name="defaultEncoding" value="UTF-8"></property>
</bean>
Upload.jsp
<body>
<center>
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="myfile"/><br>
<input type="submit" value="上传文件">
</form>
</center>
</body>
TestUploadHandler.java
package com.click369.controller;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class UploadController {
@RequestMapping(value="/upload")
public ModelAndView uploadMethod(HttpServletRequest request)throws Exception{
ModelAndView mav=new ModelAndView();
//将当前类中的ServletContext对象转换成CommonsMultipartResolver
ServletContext servletContext=request.getSession().getServletContext();
CommonsMultipartResolver commonsMultipartResolver =new CommonsMultipartResolver(servletContext);
//检查form中是否有enctype="multipart/form-data"
if(commonsMultipartResolver.isMultipart(request)){
//将HttpServletRequest对象变成多部分MultipartHttpServletRequest
MultipartHttpServletRequest multipartreq=(MultipartHttpServletRequest)request;
//从MultipartHttpServletRequest对象中得到文件名称
Iterator<String> itname=multipartreq.getFileNames();
//变量Iterator
while(itname.hasNext()){
//得到文件名称
String nameshuxing=itname.next().toString();
//根据文件名称得到具体文件
MultipartFile multipartfile=multipartreq.getFile(nameshuxing);
String newfilename=System.currentTimeMillis()+multipartfile.getOriginalFilename().substring(multipartfile.getOriginalFilename().lastIndexOf("."));
if(multipartfile!=null){
// 获取项目的根目录
String realPath = servletContext.getRealPath("/uploadpic");
File uploadpicdir = new File(realPath);
if(!uploadpicdir.exists()){
//创建保存图片的文件夹路径
uploadpicdir.mkdirs();
}
String path=uploadpicdir.getAbsolutePath()+File.separator+newfilename;
//开始上传
multipartfile.transferTo(new File(path));
}
String reqURL=request.getRequestURL().toString();
reqURL=reqURL.substring(0,reqURL.lastIndexOf("/"));
reqURL=reqURL+"/uploadpic/"+newfilename;
}
mav.setViewName("success.html");
}else{
mav.setViewName("error.html");
}
return mav;
}
}
SpringMVC的文件下载
<a href="dowload?filename=Java学习之路.txt">下在Java学习之路.txt</a>
@RequestMapping(value="/dowload")
public ResponseEntity<byte[]> dowloadMethod(HttpServletRequest req)throws Exception{
String filename=req.getParameter("filename");
String realPath = req.getSession().getServletContext().getRealPath("/uploadpic");
File uploadpicdir = new File(realPath);
File file=new File(uploadpicdir,filename);
System.out.println(file.getAbsolutePath());
HttpHeaders headers = new HttpHeaders();
headers.setContentDispositionFormData("attachment",filename);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);
}