1、MVC和SpringMVC
1.1、MVC是什么
MVC:M Model V View C Controller 模型(javabean) 视图(jsp/img) 控制器(serlvet/action)
存在的目的:把模型渲染视图,即时把模型更新到视图中
1.2、什么是SpringMVC
Spring MVC是基于MVC模式的一个框架,它解决WEB开发中常见的问题(参数接收、文件上传、表单验证、国际化、等等),而且使用简单,与spring无缝集成。
2、SpringMVC的入门程序
2.1、HelloWorld
(1)导入资源包:
(2)在classpath下添加配置文件(application.xml)
(3)编写核心类,实现接口org.springframework.web.servlet.mvc.Controller,配置到配置文件中
核心类代码:
public class HelloWorldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("HelloWorldController.handleRequest()");
String user = request.getParameter("user");//获得URL传递的参数
request.setAttribute("key", "你好");
request.getRequestDispatcher("hello.jsp").forward(request, response);//回写数据
return null;
}
}
配置文件:
<!--name:对应的是前端访问的人口 -->
<bean name="/hello" class="com.it520.controller.HelloWorldController"></bean>
(4)web.xml中配置前端控制器和加载配置文件的位置
默认加载路径WEB-INF文件夹下名为:-servlet.xml的文件
<servlet>
<!--配置前端控制器-->
<servlet-name>sprinMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!--配置加载配置文件的位置-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>sprinMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
(5)部署、启动服务器和访问
2.2、设置Serlvet的启动时机
Serlvet默认在第一次访问的时候启动,去加载项目,如果项目很大会造成第一次访问时间太长。
为了解决第一次访问很慢的问题,我们可以通过配置load-on-startup属性来设置Serlvet的启动时机。
web.xml中的配置如下:
<!-- 数值越小,启动优先级越高 -->
<load-on-startup>1</load-on-startup>
2.3、通过ModelAndView的回写值
上述的核心类中是通过HttpServletRequest和HttpServletResponse的方式来向客户端回写数值,SpringMVC通过了基于ModelAndView的回写值得方式,代码如下:
public class HelloWorldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("HelloWorldController.handleRequest()");
String user = request.getParameter("user");
// request.setAttribute("key", "你好");
// request.getRequestDispatcher("hello.jsp").forward(request, response);
ModelAndView mv = new ModelAndView();
mv.addObject("key", "你好ModelAndView");
mv.setViewName("hello.jsp");
return mv;
}
}
hello.jsp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>回写数据</title>
</head>
<body>
${key}
</body>
</html>
3、SpringMVC的执行流程
HanderMapping 请求映射处理器:
作用:根据不同的请求选择最合适的处理器(自己编写的控制器),请求映射处理器可以配置多个,谁最先匹配就执行谁。
HandlerAdapter 处理器适配:
作用: 支持多种类型的处理器,如何来执行"处理器(控制器)
4、基于全注解的方式使用SpringMVC
步骤
(1)在application.xml中开启注解扫描
(2)在application.xml中添加对springmvc驱动支持
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.it520.controller"></context:component-scan>
<!-- 添加对springmvc驱动支持 -->
<mvc:annotation-driven/>
(3)导入Spring中的AOP的包
(4)编写核心类
编写核心类,在类上添加@Controller
在方法上添加注解@RequestMapping("/method") ,方法名随意,方法参数随意,自动注入,注意:要么参数列表中有response,要么就返回modelANdView
@Controller
public class AnnoSpringMVC {
@RequestMapping("/method")
public ModelAndView method() {
System.out.println("======");
ModelAndView mv = new ModelAndView();
mv.addObject("key", "你好anno");
mv.setViewName("hello.jsp");
return mv;
}
}
(5)支持对静态资源的处理(dispatcherSerlvet把静态资源处理掉了)
<mvc:default-servlet-handler/>
5、传参方式
使用一个简单的前端页面测试,input.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>用户注册</title>
</head>
<body>
<fieldset>
<legend>用户注册1</legend>
<form action="/springMVC/value1" method="post">
<table>
<tr>
<td>用户名</td>
<td><input type="text" name="userName"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"></td>
</tr>
</table>
</form>
</fieldset>
5.1、在方法参数上带上request
@RequestMapping("/value1")
public ModelAndView value1(HttpServletRequest request) {
System.out.println("ValueDemo.value1()");
String username = request.getParameter("userName");
String password = request.getParameter("password");
User u = new User(username,password);
System.out.println(u.toString());
ModelAndView mv = new ModelAndView("input.jsp");
return mv;
}
5.2、前台参数的key和后台方法的形参名对应就能自动注入
@RequestMapping("/value2")
public ModelAndView value2(String userName,String password){
System.out.println("ValueDemo.value2()");
User u = new User(userName,password);
System.out.println(u.toString());
ModelAndView mv = new ModelAndView("input.jsp");
return mv;
}
将第一个参数名改成name
//当前台参数和后台方法的形参不一致时可以通过@RequestParam来改变传入的形参
public ModelAndView value3(@RequestParam("name") String userName ,String password) {
System.out.println("ValueDemo.value3()");
User u = new User(userName,password);
System.out.println(u.toString());
ModelAndView mv = new ModelAndView("input.jsp");
return mv;
}
5.3、对象传参方式(对象类中必须要有无参的构造方法)
@RequestMapping("/value4")
public ModelAndView value4(User u) {
System.out.println("ValueDemo.value4()");
System.out.println(u.toString());
ModelAndView mv = new ModelAndView("input.jsp");
return mv;
}
5.4、地址栏传参 localhost/delete/5
@RequestMapping("/delete/{id}")
public ModelAndView value5(@PathVariable("id") Long id){
System.out.println("delete");
System.out.println(id);
ModelAndView mv = new ModelAndView("input.jsp");
return mv;
}
5.5、配置中文乱码过滤器
在web.xml中增加如下配置
<filter>
<filter-name>hi</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>hi</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6、传值方式
后续的回显数据提供data.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>数据回显</title>
</head>
<body>
${msg }<br>
${string }<br>
${date }<br>
${user }
</body>
</html>
6.1、原始方式 request.setAttribute("","");
@RequestMapping("/data1")
public ModelAndView data1(HttpServletRequest request) {
request.setAttribute("msg", "今天你好");
ModelAndView mv = new ModelAndView("data.jsp");
return mv;
}
6.2、通过modelAndView的addObject()
@RequestMapping("/data2")
public ModelAndView data2() {
ModelAndView mv = new ModelAndView("data.jsp");
mv.addObject("msg","今天天气不错");
mv.addObject("明天天气不错");//如果只传入值,默认key为数据类型,全小写
mv.addObject(new Date());
mv.addObject(new User("xiaoming","232154"));
mv.addObject(new User("xiaomei","12154"));//后面的值会覆盖前面的值
return mv;
}
6.3、直接返回对象,需要配置视图解析器
在application.xml中配置回显数据的前缀和后缀
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property><!--设置回显数据路径的前缀,并在WEB-INF下创建一个view文件夹 -->
<property name="suffix" value=".jsp"></property><!--设置回显数据路径的后缀 -->
</bean>
@RequestMapping("/data3")
@ModelAttribute("myUser")//通过@ModelAttribute注解来设置回显数据的形参
public User data3() {
return new User("xiaoming","123");//响应视图为(前缀+请求路径+后缀)及WEB-INF/view/data3.jsp
}
在WEB-INF/view/文件夹下添加data3.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>
${myUser }
</body>
</html>
6.4、返回String,可以通过Model传值
@RequestMapping("/data4")
public String data4(Model ml){
ml.addAttribute("msg", "jttcbc");
return "show";//响应视图为(前缀+返回值+后缀)及WEB-INF/view/show.jsp
}
在WEB-INF/view/文件夹下添加show.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>
${msg }
</body>
</html>
6.5、取消前缀和后缀forward和redirect
forward叫转发,redirect叫做重定向,地址栏,数据共享,应用场景,效率,本质,次数上都有些许区别,具体的区别可参考博客:
@RequestMapping("/data5")
public String data5(Model ml){
ml.addAttribute("msg", "jttcbc5");
return "forward:hello.jsp";//直接访问根目录下的hello.jsp
}
@RequestMapping("/data6")
public String data6(Model ml){
ml.addAttribute("msg", "jttcbc6");
return "redirect:hello.jsp";//直接访问根目录下的hello.jsp
}
}
7、文件上传
(1)编写文件上传的前台页面upload.jsp,注意表单 类型:enctype=“multipart/form-data”
<%@ 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>文件上传</title>
</head>
<body>
<fieldset>
<legend>文件上传</legend>
<form action="/springMVC/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file"><br>
<input type="submit" name ="提交">
</form>
</fieldset>
</body>
</html>
(2)在application.xml中配置上传解析器
<!--上传解析器 id为固定名称 multipartResolver-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>1048576</value>
</property>
</bean>
(3)编写上传类;
@RequestMapping("/upload")
public String upload(MultipartFile file) {
System.out.println(file.getContentType());//文件类型
System.out.println(file.getName());//前台传入的名字
System.out.println(file.getOriginalFilename());//原始的名字
System.out.println(file.getSize());
//将上传的文件保存在服务器
String dir="C:/Users/Hu Liupan/Desktop/test";
FileOutputStream uts = null;
try {
InputStream ips= file.getInputStream();//上传文件的输入流
String filename = file.getOriginalFilename();//前台传入文件的原始的名字
uts = new FileOutputStream(new File (dir,filename));
IOUtils.copy(ips, uts);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(uts!=null) {
try {
uts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "redirect:upload.jsp";
}
}
8、文件下载
(1)在参数中添加response参数
(2)方法加上注解@ResponsBody
@RequestMapping("/down")
@ResponseBody//添加这样的注解,告诉SpringMVC所以的响应都由response处理
public void download(HttpServletResponse response){
File file = new File("C:/Users/Hu Liupan/Desktop/test/盲打练习.txt");
//定义输入流
FileInputStream fis = null;
try{
//设置可选择下载还是打开的窗体,没有这个代码下载的文件就会在浏览器中打开。
response.setHeader("Content-Disposition", "attachment;filename=盲打练习.txt");
fis = new FileInputStream(file);
ServletOutputStream outputStream = response.getOutputStream();
IOUtils.copy(fis, outputStream);
}catch(Exception e){
e.printStackTrace();
}finally{
if(fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
9、springMVC的拦截器
(1)拦截器类 org.springframework.web.servlet.HandlerInterceptor
preHandle:执行处理器前调用 ,返回true or false 如果为false,拦截请求
postHandle:处理器调用完成后,但是视图合并前
afterCompletion:视图合并后调用
public class DemoInteceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("DemoInteceptor.preHandle()");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("DemoInteceptor.postHandle()");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("DemoInteceptor.afterCompletion()");
}
}
(2)配置拦截器
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<bean class="com.it520.controller.DemoInteceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>