前言
ssm springmvc+spring+mybaits MVC三层架构
javaSE:认真学习,快速入门
javaWeb:认真学习
框架:研究官方文档,锻炼自学/笔记/项目能力
MVC
mvc是模型model,视图view,控制器controller的简写,是一种软件设计思想。
是将业务逻辑、数据、显示分离的方法来组织代码
model1时代
model2时代
model2这样不仅提高了代码的复用率与项目的拓展性,且大大降低了项目的维护成本,Model1的实现方式比较简单,适用于开发小规模项目,Model中jsp页面兼View和Controller两种角色,将控制逻辑和表现逻辑混杂在一起,从而导致代码的重用率非常低,增加了应用的拓展性和维护的难度,model2消除了model1的缺点。
学习复习前提
新建项目
在pom.xml中添加依赖
创建子项目
然后右键点击增加框架,增加web框架
servlet用来处理请求
package com.mmz.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Classname com.mmz.servlet.HelloServlet
* @Description TODO
* @Date 2021/2/28 19:59
* @Created by mmz
*/
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1 获取前端参数
String method = req.getParameter("method");
if(method.equals("add")){
req.getSession().setAttribute("msg","执行了add方法");
}
if(method.equals("delete")){
req.getSession().setAttribute("msg","执行了delete方法");
}
// 2 调用业务层
// 3 视图转发或者重定向
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
jsp返回页面
<%--
Created by IntelliJ IDEA.
User: mmz
Date: 2021/2/28
Time: 20:02
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>test</title>
</head>
<body>
${msg}
</body>
</html>
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>hello</servlet-name>
<servlet-class>com.mmz.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!-- <session-config>-->
<!-- <session-timeout>15</session-timeout>-->
<!-- </session-config>-->
<!-- <welcome-file-list>-->
<!-- <welcome-file>index.jsp</welcome-file>-->
<!-- </welcome-file-list>-->
</web-app>
总结 mvc框架可能要做哪些事情
将url映射到java类或者java类的方法
封装用户提交的数据
处理请求-调用相关的业务-封装响应数据
将响应的数据进行渲染 .jsp/html 等表示层数据
中心控制器DispatcherServlet
spring的web框架围绕DispathcerServlet设计,dispatcherservlet的作用是将请求分发到不同的处理器。
现在可以基于Controller的注解声明处理器。
DispatcherServlet本质也是一个Servlet
Springmvc 执行流程
配置dispatcherServlet
<?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>
</web-app>
执行handler
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<bean id="/hello" class="com.mmz.controller.HelloController"></bean>
</beans>
找到相应Controller并且返回视图模型
package com.mmz.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Classname HelloController
* @Description TODO
* @Date 2021/3/1 21:10
* @Created by mmz
*/
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","HelloSpringMVC");
modelAndView.setViewName("hello");
return modelAndView;
}
}
具体的执行流程
这部分以前整理过,就是从前端发送请求到后端,首先先到DispatcherServlet,然后HandlerMapping处理器映射器去寻找相应的handler,在根据handler被HandlerAdapter处理器适配器去执行。Handler最后会执行controller,controller把执行的信息返回ModelAndView给HandlerApadter,然后dispatcherServlet调用视图解析器ViewResolver去解析视图。最后视图呈现给用户。
注解开发SpringMVC
首先还是要配置web.xml
配置dispatcherServlet
<?xml version="1.0" encoding="GBK"?>
<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>
</web-app>
配置注解使用SpringMVC
无论哪种方式配置SpringMVC都需要配置处理器映射器,处理器适配器,视图解析器
<?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-4.2.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="com.mmz.controller"></context:component-scan>
<!--SpringMVC不处理静态资源 .css .js .html 不走视图解析-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--原来需要配置两个,现在只需要配置-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
最后编写Controller
package com.mmz.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Classname HelloController
* @Description TODO
* @Date 2021/3/2 14:13
* @Created by mmz
*/
@Controller
@RequestMapping("/hello")
public class HelloController {
/*localhost:8080/hello/h1*/
@RequestMapping("/h1")
public String hello(Model model){
// 封装数据
model.addAttribute("msg","hello,springmvc");
return "hello"; // 会被视图解析器处理
}
}
Controller注解,就是标记该类是个Controller,与extends一样,是继承类。
RequestMapping标记url,在类上是上级url,方法是下级url
需要在里面封装数据,使用Model封装,同样的增加属性
最后返回值return的字符串,就是根据web.xml配置的dispatcherServlet的地方的jsp
深入学习Controller
第一种implement Controller接口
package com.mmz.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Classname ControllerTest1
* @Description TODO
* @Date 2021/3/2 15:09
* @Created by mmz
*/
public class ControllerTest1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","ControllerTest1");
modelAndView.setViewName("test");
return modelAndView;
}
}
然后在spring中配置bean
<bean name="/text1" class="com.mmz.controller.ControllerTest1"></bean>
这种方式,一个控制器中只有一种方法, 如果要多个方法使用,需要定义多个Controller,定义的方式比较麻烦。
使用注解
package com.mmz.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Classname ControllerTest2
* @Description TODO
* @Date 2021/3/2 15:17
* @Created by mmz
*/
@Controller // 代表被Spring托管
public class ControllerTest2 {
@RequestMapping("/t2")
public String test(Model model){
model.addAttribute("msg","ControllerTest2");
return "test";
}
}
RequestMapping
注解应用于映射url到控制器或一个特定的处理程序方法。可用于类或者方法上,用于类上表示类中的所有响应请求的方法都是以该地址为父路径。
RestFul风格
Restful就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
package com.mmz.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Classname RestController
* @Description TODO
* @Date 2021/3/2 19:58
* @Created by mmz
*/
@Controller
public class RestController {
@RequestMapping("/add")
public String test(int a, int b, Model model){
int result = a+b;
model.addAttribute("msg","结果为"+result);
return "test";
}
}
我们输入urlhttp://localhost:8080/springmvc_04_controller_war_exploded/add/?a=1&b=2
才能得到结果
路径变量
因为如果这样,还需要在url写?后面加上在变量,但是这样不是纯真的restful风格。
可以使用@PathVariable
注解,让方法参数的值对应绑定到一个URL模板变量上。
package com.mmz.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Classname RestController
* @Description TODO
* @Date 2021/3/2 19:58
* @Created by mmz
*/
@Controller
public class RestController {
@RequestMapping("/add/{a}/{b}")
public String test(@PathVariable int a,@PathVariable int b, Model model){
int result = a+b;
model.addAttribute("msg","结果为"+result);
return "test";
}
}
url输入为
http://localhost:8080/springmvc_04_controller_war_exploded/add/1/12
结果为
可以控制传递方法
在requestMapping下面的RequestMethod[] method()
public enum RequestMethod {
GET,
HEAD,
POST,
PUT,
PATCH,
DELETE,
OPTIONS,
TRACE;
private RequestMethod() {
}
}
可以控制几种方法
@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
就是用delete方式的请求
也可以直接用/*@GetMapping*/
这种注解来直接标记为get方法
提交的域名名称和处理方法的参数不一样
就比如在url传递的参数 ?username=mmz
但是我用String name接受这个参数,需要用这个注解@RequestParam来实现
@RequestParam(“username”) String name;
接受前端用户传递的参数,判断参数的名字,假设名字直接在方法上,可以直接使用
假设传递的是一个对象User,匹配User对象中的字段名。如果名字一致直接匹配,如果不是匹配不到
前端返回类型
返回类型其实有三个,model, modelmap , modelandview
model:只有寥寥几个方法只适用于储存数据,简化了新手对Model对象的操作和理解。
modelmap: 继承了LinkedMap,除了实现了资深的一些方法,同样继承了LinkedMap的方法和特性
modelandview:可以在存储数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。
配置SpringMVC的乱码过滤器
使用过滤器
<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>
Controller返回json数据
package com.mmz.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mmz.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Classname UserController
* @Description TODO
* @Date 2021/3/3 20:46
* @Created by mmz
*/
@Controller
public class UserController {
// 不会走视图解析器,会直接返回一个字符串
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")
@ResponseBody
public String json1() throws JsonProcessingException {
// jackson , objectMapper
ObjectMapper objectMapper = new ObjectMapper();
// 创建一个对象
User user = new User("mmz",18,"男");
String string = objectMapper.writeValueAsString(user);
return string;
}
}
解决json乱码问题
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
RestController
这个注解在类上注解,表示返回的都是json格式的字符串,不用在每个方法上面都注解@ResponseBody