1.MVC与三层架构
- MVC即是一种开发模式(看了图一目了然)
- 三层架构
表现层:用于展示数据
业务层:是处理业务需求
持久层:和数据库交互
2.SpringMVC概述
*概述: SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于 Spring FrameWork 的后续产品,已经融合在 Spring Web Flow 里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。
- SpringMVC在三层架构中的位置
3.SpringMVC与Struts2的区别
- 共同点:
1.它们都是表现层框架,都是基于 MVC 模型编写的。
2.它们的底层都离不开原始 ServletAPI。
3.它们处理请求的机制都是一个核心控制器。 - 区别:
1.Spring MVC 的入口是 Servlet, 而 Struts2 是 Filter
2.Spring MVC 是基于方法设计的,而 Struts2 是基于类,Struts2 每次执行都会创建一个动作类。所以 Spring MVC 会稍微比 Struts2 快些。
3.Spring MVC 使用更加简洁,同时还支持 JSR303, 处理 ajax 的请求更方便(JSR303 是一套 JavaBean 参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们 JavaBean 的属性上面,就可以在需要校验的时候进行校验了。)
4.Struts2 的 OGNL 表达式使页面的开发效率相比 Spring MVC 更高些,但执行效率并没有比 JSTL 提升,尤其是 struts2 的表单标签,远没有 html 执行效率高。
4.SpringMVC中的组件
SpringMVC框架是基于组件方式执行的:
- 前台控制器
- 处理器映射器
- 处理器适配器
- 试图解析器
5.@RequestMapping注解
1.作用:用于建立请求 URL 和处理请求方法之间的对应关系。
2.出现位置:可以在类上(作为一级目录),也可以在方法上(作为二级目录),若类上有的话那么前台访问时的路径就要写一级路径+二级路径(user/hello)
3.属性:
- value:用于指定请求的 URL。
- method:用于指定请求的方式。
- params:用于指定限制请求参数的条件。
- headers:用于指定限制请求消息头的条件。
6.请求参数的绑定
<a href="params/getParams?username=smx&password=123">请求参数的绑定</a>
对应后台的代码为:
@Controller
@RequestMapping("/params")
public class ParamsTest {
@RequestMapping("/getParams")
public String getParams(String username,String password){
System.out.println("测试请求参数的绑定");
System.out.println("用户名为:"+username);
System.out.println("密码为:"+password);
return "success";
}
}
7.常用注解
1.@RequestParam
作用:
把请求中指定名称的参数给控制器中的形参赋值。
属性:
value:请求参数中的名称。
required:请求参数中是否必须提供此参数。默认值:true。表示必须提供,如果不提供将报错
2.@RequestBody
作用:
用于获取请求体内容。直接使用得到是 key=value&key=value…结构的数据。
get 请求方式不适用。
属性:
required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值
为 false,get 请求得到是 null。
3.@PathVariable
作用:
用于绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。
url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。
属性:
value:用于指定 url 中占位符名称。
required:是否必须提供占位符。
4.@RequestHeader
作用:
用于获取请求消息头。
属性:
value:提供消息头名称
required:是否必须有此消息头
5.@CookieValue
作用:
用于把指定 cookie 名称的值传入控制器方法参数。
属性:
value:指定 cookie 的名称。
required:是否必须有此 cookie。
6.@ModleAttribute
作用:
该注解是 SpringMVC4.3 版本以后新加入的。它可以用于修饰方法和参数。出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回值的方法。出现在参数上,获取指定的数据给参数赋值。
属性:
value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key。
应用场景:
当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
例如:
我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数
据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。
7.@SessionAttribute
作用:
用于多次执行控制器方法间的参数共享。
属性:
value:用于指定存入的属性名称
type:用于指定存入的数据类型。
学习这个注解时有一个问题就是----为什么要和Model扯上关系呢(经过思考得知是因为有了这个注解才会有方法间的参数共享所以model是为了演示共享的问题)
8. SpringMVC最基本的配置
springmvc-servlet.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: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/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="smx.bedroom"></context:component-scan>
<!--加了这行代码之后自动配置处理器映射器和处理器适配器-->
<mvc:annotation-driven />
<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--用于处理乱码问题-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
9.数据写回前端
数据显示到前端
第一种 : 通过ModelAndView
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
第二种 : 通过ModelMap
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("name",name);
System.out.println(name);
return "hello";
}
第三种 : 通过Model(最常用的)
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
10.重定向与转发
@Controller
public class ForwordRedirect {
@RequestMapping("/tf")
public String testForward(Model model){
model.addAttribute("msg","testForword");
//return "success";//存在试图解析器的转发它等价于-->return "forward:/WEB-INF/jsp/success.jsp"
//return "/WEB-INF/jsp/success.jsp";//不存在试图解析器的转发
return "forward:/WEB-INF/jsp/success.jsp";//存在试图解析器的转发
}
@RequestMapping("/tre")
public String testreRedirect(Model model){
model.addAttribute("msg","testreRedirct");
return "redirect:/post.jsp";//重定向
//return "/post.jsp";//没有试图解析器的重定向
}
}
11.Restful风格
@Controller
public class RestfulController {
@GetMapping("/tr/{a}/{b}")
//@RequestMapping(value ="/tr/{a}/{b}",method = RequestMethod.GET)
public String testRestful(@PathVariable int a, @PathVariable int b, Model model){
int result=a+b;
model.addAttribute("msg","结果为:"+result);
return "success";
}
@PostMapping("/tr2/{a}/{b}")
//@RequestMapping(value ="/tr/{a}/{b}",method = RequestMethod.POST)
public String testRestful2(@PathVariable int a, @PathVariable int b, Model model){
int result=a+b;
model.addAttribute("msg","结果为:"+result);
return "success";
}
}
12.响应json数据
//@Controller
@RestController//它的作用等同于@RequestBody有了它将不再走视图解析器了之间返回字符串
public class JsonController {
//@RequestBody有了它将不再走视图解析器了之间返回字符串
@RequestMapping("/testjson")
public String testjson() throws JsonProcessingException {
User user = new User();
user.setAge(20);
user.setName("smx");
ObjectMapper mapper=new ObjectMapper();
String s = mapper.writeValueAsString(user);
return s;
}
}
13.文件的上传和下载
package smx.bedroom.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@Controller
public class FileController {
//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
//获取文件名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
//如果文件名为空,直接回到首页!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上传文件名 : "+uploadFileName);
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
//如果路径不存在,创建一个
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上传文件保存地址:"+realPath);
InputStream is = file.getInputStream(); //文件输入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流
//读取写出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "success";
}
/*
* 采用file.Transto 来保存上传的文件
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上传路径保存设置
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上传文件地址
System.out.println("上传文件保存地址:"+realPath);
//通过CommonsMultipartFile的方法直接写文件(注意这个时候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
return "success";
}
/**
* 文件下载
*/
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "Java面试题以及答案.pdf";
//1、设置response 响应头
response.reset(); //设置页面不缓存,清空buffer
response.setCharacterEncoding("UTF-8"); //字符编码
response.setContentType("multipart/form-data"); //二进制传输数据
//设置响应头
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、 读取文件--输入流
InputStream input=new FileInputStream(file);
//3、 写出文件--输出流
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、执行 写出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return "success2";
}
}
14.拦截器的配置
<!--拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**/"/>
<bean class="smx.bedroom.config.MyIntercepter"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**/"/>
<bean class="smx.bedroom.config.UserIntercepter"/>
</mvc:interceptor>
</mvc:interceptors>