MVC
这位的笔记很好:https://blog.csdn.net/m0_46357847/article/details/109753731?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-2.control
MVC概念
model,view,controller
用处:模块分离,降低耦合度!
SpringMVC架构
Nosql:redis缓存
SpringMVC作用
l 天生与Spring框架集成,如:(IOC,AOP)
l 支持Restful风格
l 支持灵活的URL到页面控制器的映射
SpringMVC主要组件
-
DispatcherServlet:前端控制器
-
Controller:处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理
-
HandlerMapping :请求映射到处理器,找谁来处理,如果映射成功返回一个HandlerExecutiongChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器对象)
-
ViewResolver : 视图解析器,找谁来处理返回的页面。把逻辑视图解析为具体的View,进行这种策略模式,很容易更换其他视图技术;
如InternalResourceViewResolver将逻辑视图名映射为JSP视图 -
LocalResolver:本地化、国际化
-
MultipartResolver:文件上传解析器
-
HandlerExceptionResolver:异常处理器
Spring工作流程
1、DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
我们假设请求的url为 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
http://localhost:8080服务器域名
SpringMVC部署在服务器上的web站点
hello表示控制器
通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器。
2、HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping,HandlerMapping根据请求url查找Handler。
3、HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。
4、HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。
5、HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
6、Handler让具体的Controller执行。
7、Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。
8、HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet。
9、DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名。
10、视图解析器将解析的逻辑视图名传给DispatcherServlet。
11、DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。
12、最终视图呈现给用户。
SpringMVC
步骤
1.新建一个web项目
2.导入相关jar包
3.编写web.xml , 注册DispatcherServlet
4.编写springmvc配置文件
5.接下来就是去创建对应的控制类 , controller
6.最后完善前端视图和controller之间的对应
7.测试运行调试.
控制器@Controller
- @Controller声明为控制器
- 开启spring注解扫描
- 作用:控制器负责解析用户的请求并将其转换为一个模型(model)
- 增加一个TestController类,使用注解实现:
/**
* @description: TestController
* @author: laizhenghua
* @date: 2020/11/19 9:34
*/
@Controller // @Controller注解的类会自动添加到Spring上下文中
public class TestController {
@RequestMapping(value = "/test") // 映射访问路径
public String test(Model model){
// Spring MVC会自动实例化一个Model对象用于向视图中传值,最终会传入Request域对象中
model.addAttribute("message","hello @Controller");
// 返回视图位置,如果返回值是String,并且有具体页面可以跳转,就会被视图解析器解析。
return "test";
}
}
- message已经被给定值,前端就能用message了
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${requestScope.message}
</body>
</html>
- 前端的代码可复用,只需在后端给定message不同的值即可,即视图可复用,控制器与视图弱耦合
@RequestMapping
- 作用:用于建立请求 URL 和处理请求方法之间的对应关系。
- 放在类上或者方法上:
@Controller
@RequestMapping("/admin")
public class TestController {
@RequestMapping("/h1")
public String test(){
return "test";
}
}
访问路径就是:http://localhost:8080/项目名/admin/h1
- 其中的属性:
value:用于指定请求的 URL。它和 path 属性的作用是一样的。
method:用于指定请求的方式。@RequestMapping(path = “/test”,method = {RequestMethod.GET})
headers:用于指定限制请求消息头的条件。
params:用于指定限制请求参数的条件。它支持简单的表达式。要求请求参数的 key 和 value 必须和配置的一模一样。
比如:
params = {"accountName"} # 表示请求参数必须有 accountName
params = {"moeny!100"} # 表示请求参数中 money 不能是 100。
params = {"userId=1"} # 表示请求参数中userId必须是1
注意: 以上四个属性只要出现 2 个或以上时,他们的关系是 与 的关系。
Restful
概念
- Restful就是一个资源定位及资源操作的风格。风格。风格!
- 资源操作:POST、DELETE、PUT、GET(传统的只有post get)
- 分别是:添加、删除、修改、查询
测试
传统传参
/**
* @description: 测试RestFul风格
* @author: laizhenghua
* @date: 2020/11/19 10:49
*/
@Controller
public class RestFulController {
@RequestMapping(path = "/add")
public String test1(int a, int b, Model model){
int sum = a + b;
model.addAttribute("message","a + b = "+sum); // 把数据存入request域对象中
return "test"; // /WEB-INF/jsp/test.jsp
}
}
Restful传参
在Spring MVC中可以使用 @PathVariable 注解,让方法参数的值对应绑定到一个URI模板变量上。
/**
* @description: 测试RestFul风格
* @author: laizhenghua
* @date: 2020/11/19 10:49
*/
@Controller
public class RestFulController {
@RequestMapping(path = "/add/{a}/{b}") // 映射访问路径
public String test1(@PathVariable int a, @PathVariable int b, Model model){
int sum = a + b;
model.addAttribute("message","a + b = " + sum); // 把数据存入request域对象中
return "test"; // /WEB-INF/jsp/test.jsp
}
}
路径变量传参的好处
- 使路径变得更加简洁
- 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法,如这里访问是的路径是/commit/1/a,则路径与方法不匹配,而不会是参数转换失败
所有的浏览器地址栏请求默认是HTTP GET请求
RequestMapping一组变形:
@GetMapping = @RequestMapping(method = RequestMethod.GET)
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
SpringMVC跳转
无需视图解析器
@GetMapping(path = "test/add")
public String test3(Model model){
model.addAttribute("message","执行添加操作!");
/*
在没有视图解析器的情况下,如果我们返回jsp文件的全限定名称依旧能在浏览
器里访问得到。这种情况下相当于转发!路径不变。
*/
return "/WEB-INF/jsp/test.jsp";
}
@GetMapping(path = "test/add")
public String test3(Model model){
model.addAttribute("message","执行添加操作!");
// 转发
return "forward:/WEB-INF/jsp/test.jsp";
}
@GetMapping(path = "test/add")
public String test3(Model model){
model.addAttribute("message","执行添加操作!");
// 重定向
return "redirect:/index.jsp";
}
Json详解
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
JSON是一种轻量级的数据交换格式。
@ResponseBody 使用此注解后,它就不会走视图解析器,会直接返回一个字符串!
/**
* @description: 控制器UserController
* @author: laizhenghua
* @date: 2020/11/21 9:54
*/
@Controller
public class UserController {
@ResponseBody
@RequestMapping(path = "/test1")
public String test1() throws JsonProcessingException {
// 创建一个user对象
User user = new User(1,"alex",21,"男");
// 将user对象转换为json字符串
ObjectMapper mapper = new ObjectMapper();
String userJson = mapper.writeValueAsString(user);
return userJson;
}
}
@Controller需要配合@ResponseBody才能实现方法返回json字符串,但是我们有更简洁的方案让方法返回json字符串!
在类上直接使用 @RestController ,这样子,里面所有的方法都只会返回 json 字符串了,不用再每一个都添加@ResponseBody !我们在前后端分离开发中,一般都使用 @RestController ,十分便捷!
/**
* @description: 控制器UserController
* @author: laizhenghua
* @date: 2020/11/21 9:54
*/
@RestController // 使用此注解代替@Controller
public class UserController {
@RequestMapping(path = "/test1")
public String test1() throws JsonProcessingException {
// 创建一个user对象
User user = new User(1,"alex",21,"男");
// 将user对象转换为json字符串
ObjectMapper mapper = new ObjectMapper();
String userJson = mapper.writeValueAsString(user);
return userJson;
}
}
记得解决中文乱码问题。
拦截器
作用
1、SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
2、可以定义拦截器链,拦截器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链 中的拦截器会按着定义的顺序执行。
3、拦截器和过滤器的功能比较类似,有区别
过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
拦截器是SpringMVC框架独有的,只有使用了SpringMVC框架的工程才能使用。
过滤器 url-pattern 配置了/*,可以拦截任何资源。
拦截器只会对控制器中的方法进行拦截,如果访问的是jsp/html/css/image/js是不会进行拦截。
4、拦截器也是AOP思想的一种实现方式
5、想要自定义拦截器,需要实现HandlerInterceptor接口。
举例:登陆拦截器
1、有一个登陆页面,需要写一个controller访问页面。
2、登陆页面有一提交表单的动作。需要在controller中处理。判断用户名密码是否正确。如果正确,向session中写入用户信息。返回登陆成功。
3、拦截用户请求,判断用户是否登陆。如果用户已经登陆。放行, 如果用户未登陆,跳转到登陆页面。
登陆界面login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String path = request.getContextPath();
%>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<h1>登录页面</h1>
<form action="<%=path%>/user/login" method="post">
username : <input type="text" name="username">
password : <input type="password" name="password">
<input type="submit" value="登录">
</form>
</body>
</html>
Controller处理请求
@RequestMapping(path = "/login",method = RequestMethod.POST)
public String userLogin(@RequestParam String username, @RequestParam String password, HttpSession session){
session.setAttribute("user",username);
// 注销时,把这个属性节点remove即可如:session.removeAttribute("user");
/*
这里写的并不严谨,用户名和密码应该走数据库,并且要考虑查询错误的情况
*/
return "main";
}
登陆成功页面main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<h1>hello ${sessionScope.user}</h1>
</body>
</html>
编写用户登陆拦截器
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
User user = (User)session.getAttribute("user");
if(user != null){
return true;
}
// 如果没哟登录,就转发到登录页面
request.getRequestDispatcher("/login.jsp").forward(request,response);
return false;
}
}
在配置文件中注册拦截器
<!--登录拦截器-->
<mvc:interceptor>
<mvc:mapping path="/user/*"/>
<mvc:exclude-mapping path="/user/login"/><!--登录请求不进行拦截-->
<bean class="com.howie.interceptor.LoginInterceptor"/>
</mvc:interceptor>