1、springmvc是什么?
springmvc全称是spring web mvc,是spring框架一部分,是专门做web开发的。主要把业务逻辑从界面中解耦,降低耦合度。
2、springmvc架构原理
原理简写:DispatcherServlet-->映射器-->适配器-->视图解析器-->页面
3、springmvc入门
项目地址:https://github.com/zhongyushi-git/spring-collection.git。下载代码后,示例代码在maven-springmvc-demo文件夹下。
3.1 导入依赖
新建一个maven的web项目,在pom.xml导入
properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring.version>5.3.4</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> </dependency> </dependencies>
3.2编写配置文件
1)编写web.xml
在web.xml中配置如下内容:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<!--springmvc前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
其中servlet是用来拦截请求,交给spring管理;init-param来加载配置文件;url-pattern常用/。
2)编写springmvc.xml
在src目录下创建springmvc.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<beans>
3.3开发Controller类
新建包com.zxh.controller,包下创建一个HelloController类,来处理请求,相当于servlet。
package com.zxh.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController2 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("test");//设定视图,相对的是web
return modelAndView;
}
}
3.4新建页面并配置
1)在webapp下新建views文件夹,在文件夹下新建test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> 你好啊 </body> </html>
2)配置视图解析器
在springmvc.xml中配置视图解析器,代码如下:
<!--配置视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/views/"></property> <property name="suffix" value=".jsp"></property> </bean>
3.5使用xml方式配置接口
在springmvc.xml中配置:
<!-- 把SpringMvc类交给springmvc管理 -->
<bean id="hello" class="com.zxh.controller.HelloController2"></bean>
<!-- 配置适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- 配置处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!--key表示的是访问的路径-->
<prop key="/hello">hello</prop>
</props>
</property>
</bean>
配置后添加tomcat并启动,在浏览器访问http://localhost:8080/maven_springmvc_demo_war/hello看到test.jsp编写的内容,说明xml配置成功。
3.6使用注解方式配置接口
除了上面xml方式外,还可以使用注解方式。
1)在springmvc.xml配置
以上代码可以简写为两行:
<!--开启注解-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--包扫描-->
<context:component-scan base-package="com.zxh.controller"/>
2)开发controller类
然后新建一个HelloController类:
package com.zxh.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class HelloController2 {
@RequestMapping("/hello2")
public ModelAndView hello(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("test");
return modelAndView;
}
}
3)配置后添加tomcat并启动,在浏览器访问http://localhost:8080/maven_springmvc_demo_war/hello2看到test.jsp编写的内容,说明xml配置成功。
3.7其他配置
1.编码处理:设置一个编码过滤器,参数等不在乱码。web.xml中配置:
<filter> <filter-name>CharacterEncodingFilter</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
4、参数绑定
4.1什么是参数绑定
springmvc接收请求的key/value串(比如:id=2&type=101),经过类型转换,将转换后的值赋值给controller方法的形参,这个过程就叫参数绑定。
4.2默认支持的类型
在controller方法形参中如下类型是可以直接绑定成功,springmvc框架给以下类型的参数直接赋值:
HttpServletRequest:通过request对象获取请求信息
HttpServletResponse:通过response处理响应信息
HttpSession:通过session对象得到session中存放的对象
4.3简单数据类型参数绑定
1)简单数据类型
Integer、string、boolean、float等
2)绑定规则
当请求的参数的名称和controller方法的形参名一致时可以绑定成功。
3)绑定的注解
@RequestParam:取别名
@RequestBody:把请求体中的数据封装到对象中,请求体中的内容必须是json格式。
@Valid:数据校验,如验证对象的某一属性是否为空。
如果每个方法都有返回值,那么可以在这个类的上面添加@RestController,它其实是@Controller+@ResponseBody的组合。它的返回值已经是json格式的数据了。
4)数据验证案例:验证前端传入的对象的密码是否是空
第一步:添加需要的依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.18</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.3.6.Final</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.10.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.10.0</version> </dependency>
第二步:创建User对象并在实体类的密码属性上加注解
package com.zxh.entity;
import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;
@Data
public class User {
@NotBlank
private String username;
private String password;
}
第三步:创建UserController并在controller的方法里面加注解和错误判断
package com.zxh.controller;
import com.zxh.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.validation.Valid;
import java.util.List;
@Controller
public class UserController {
@RequestMapping(value = "/add",method = RequestMethod.POST)
public void add(@Valid @RequestBody User user, BindingResult errors) {
//是否验证不通过
if (errors.hasErrors()) {
List<ObjectError> allErrors = errors.getAllErrors();
for (ObjectError err : allErrors) {
System.out.println(err);
}
} else {
System.out.println(user);
}
}
}
使用postman使用post请求发送json数据,当username没有传值时就会打印错误信息。
5)别名绑定
如果请求的参数的名称和controller方法的形参名不一致时,如何绑定?就要使用@RequestParam进行绑定。
加入传递的参数是id,而接收的参数是ids,要@RequestParam将请求的参数名为ids的值绑定方法形参的id上,Value可以省略。
@RequestMapping("/get")
public void get(@RequestParam(value = "id") int ids) {
System.out.println(ids);
}
6)多个参数绑定
多个参数就直接把参数的名称和类型列举出来。
@RequestMapping("/get2")
public void get2(String username, String password) {
System.out.println(username + " " + password);
}
4.4简单pojo参数绑定
简单pojo:pojo中都基本类型,如上述的User对象,已经举例,在此略。
4.5包装pojo类型
一个类中不仅有简单数据类型,还有对象属性。那么页面需要使用相应的类标识属性名,如下:
<form method="get" action="add2"> <input type="text" name="name"> <input type="text" name="user.username"> <input type="text" name="user.password"> <input type="submit"> </form>
实体类
package com.zxh.entity;
@Data public class OtherUser { private String name; private User user; }
获取内容
@RequestMapping("/add2") public void login5(OtherUser otherUser){ System.out.println(otherUser); }
4.6数组类型参数绑定
<form method="get" action="add3"> <input type="checkbox" name="hobby" value="篮球">篮球 <input type="checkbox" name="hobby" value="足球">足球 <input type="checkbox" name="hobby" value="羽毛球">羽毛球 <input type="submit"> </form>
获取选中的内容
@RequestMapping("/add3") public void login3(String[] hobby){ for (String s : hobby) { System.out.println(s); } }
5、RequestMapping的设置
requestMapping注解的作用:对controller方法进行映射。
5.1通用映射
URL路径映射:requestMapping指定url,对controller方法进行映射,如@RequestMapping("/login")
为了更好的管理url,为了避免url冲突,可以在类上再使用requestMapping指定根url,如下,使用/user/login进行访问:
@Controller @RequestMapping("/user") public class UserController {
@RequestMapping("/login") public void login2(User user){ System.out.println(user); }
}
5.2限定请求方法
通过requestMapping的method限制http的请求方法,可以提高系统安全性,只允许通过指定的请求才能访问,如下代码指定只能通过get请求访问:
@RequestMapping(value="/login",method = RequestMethod.GET) public void login(String username,String password){ System.out.println(username+" "+password); }
不过一般不使用这种方式,即它有优化后的用法。
映射的注解 | 说明 |
@GetMapping | 只接受get请求,用于查询 |
@PostMapping | 只接受post请求,用于添加 |
@PutMapping | 只接受put请求,用于修改 |
@DeleteMapping | 只接受delete请求,用于删除 |
后期都会使用这种方式进行开发。
6.Controller方法返回值
6.1返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定逻辑视图名。在入门案例就已介绍,在此略。
6.2返回Void
这样方式类似原始serlvet 的开发。响应结果有三种方法:
1)使用request转发页面,如下:request.getRequestDispatcher("index.html").forward(request, response);
2)通过response页面重定向:response.sendRedirect("url")
3)通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json串");
6.3返回String(推荐使用)
1)页面转发方式:格式是forward:转发地址(不能写http://,只能写action的地址)。特点是转发的上一个请求request和要转发的地址共用request,转发后浏览器的地址是不变化。
@RequestMapping("/login")
public String login1(){
return "forward:views/login.jsp";
}
2)页面重定向方式:格式是redirect:重定向地址(比如:http://.....)。特点是重定向的上一个请求request和要重定向的地址不共用request,重定后浏览器的地址是变化的。
@RequestMapping("/login2")
public String login2(){
return "redirect:views/login.jsp";
}
3)表示逻辑视图名:返回一个string,如果即不是转发格式,也不是重定向的格式,就表示一个逻辑视图名。这里并没有写login.jsp,原因是在springmvc.xml中已经配置了视图解析器的前缀和后缀。
@RequestMapping("/login3") public String login3(){ return "login"; }
可以看出,重定向和页面转发都需要指定页面的全路径,页面后缀不能省略,而第三种方式就简单很多。
7.Springmvc文件上传
7.1导入依赖
在pom.xml加入
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency>
7.2编写页面
1)编写文件上传的页面upload.jsp。在webapp下新建upload.jsp,内容如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>文件上传</title> </head> <body> <!--文件上传必须按照下面的格式写,缺一不可--> <form action="upload" enctype="multipart/form-data" method="post"> <input type="file" name="file"> <input type="submit"> </form> </body> </html>
2)编写上传提示的页面success.jsp。在views目录下新建success.jsp,内容如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>上传提示</title> </head> <body> 文件上传成功 </body> </html>
7.3创建controller
新建UploadController类,作为文件上传的接口
package com.zxh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @Controller public class UploadController { @RequestMapping("/upload") public String upload(MultipartFile file) throws IOException { //多文件上传MultipartFile[] file,遍历这个数组 if (file != null && file.getOriginalFilename() != null && !file.getOriginalFilename().equals("")) { //获取文件的名字 String fileName = file.getOriginalFilename(); //获取文件的后缀名 int index = fileName.lastIndexOf("."); //UUID这个方法是给文件命名,不重名 String newFileName = UUID.randomUUID() + fileName.substring(index); File NewFile = new File("D:\\upload", newFileName); //把上传的文件的内容保写到保存的位置 file.transferTo(NewFile); } return "success"; } }
需要注意,指定的路径是D:\\upload,此路径必须存在,否则会报错。
7.4配置文件解析器
在springmvc.xml中配置文件解析器
<!-- Multipart解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置上传文件的最大尺寸为5MB --> <property name="maxUploadSize"> <value>5242880</value> </property> </bean>
启动项目,访问http://localhost:8080/maven_springmvc_demo_war/upload.jsp上传一张图片,会提示上传成功。
8.处理json数据
处理json数据需要用到两个注解@RequestBody和@ResponseBody。@RequestBody注解将json数据转成java对象 ,@ResponseBody注解实现将java对象转成json输出。
对于@RequestBody在前面参数绑定的章节已经使用过了,在此略,不过需要注意的是,必须导入处理json数据的依赖,如jackjson、falstjson。主要讲解@ResponseBody的作用。
8.1@ResponseBody的作用
在前面的controller中,我们都使用string返回的是视图或页面,那么能不能直接返回文字信息呢?当然这就是ResponseBody的作用了,且看下面的代码说明。
8.2处理器映射器和适配器
修改springmvc.xml文件,把标签<mvc:annotation-driven>修改如下
<!--配置注解处理器映射器和适配器--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"> <property name="supportedMediaTypes" value="application/json"/> <property name="features"> <array> <value>WriteMapNullValue</value> <value>WriteDateUseDateFormat</value> </array> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
8.3创建测试的接口
在HelloController2类中加入两个方法
@ResponseBody @RequestMapping(value = "/hello3", produces = "text/html;charset=UTF-8") public String hello3() { return "你好啊,ResponseBody"; } @ResponseBody @RequestMapping(value = "/hello4") public User hello4() { User user = new User(); user.setPassword("123"); user.setUsername("傻子"); return user; }
这两个方法分别返回string类和对象类型,返回string类型时如有中文,需设置编码,否则访问时中文显示的是?。而返回对象类型就不需要,也是推荐的用法。分别访问这两个方法,可以看到返回的数据。
8.4注解优化
加入一个controller中的所有方法只是返回一个需要的对象,而不是页面,那么对于每个方法都加@ResponseBody也是可以的,但是显得非常的麻烦,这时就可以使用@RestController这个注解。它放在类上,那么就表明此类中的所有方法都返回json数据而不是页面,不能页面跳转。它等于@Controller+@ResponseBody,是不是简化了很多。
@RestController public class HelloController2 { @RequestMapping(value = "/hello3", produces = "text/html;charset=UTF-8") public String hello3() { return "你好啊,ResponseBody"; } @RequestMapping(value = "/hello4") public User hello4() { User user = new User(); user.setPassword("123"); user.setUsername("傻子"); return user; } }
9.springmvc对rest的支持
RESTful,即Representational State Transfer的缩写,表现层状态转化。所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。
9.1基本操作
1)GET用来获取资源,对应GetMapping。
2)POST用来新建资源(也可以用于更新资源),对应PostMapping
3)PUT用来更新资源,对应PutMaping(不常用)
4)DELETE用来删除资源。对应DeleteMapping
9.2 url模板映射
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。
映射的格式是@RequestMapping(value="/ user/{id}"):{×××}占位符,请求的URL可以是“/user/1”或“/user/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。其用法如下模板:
@GetMapping("/user/{abc}") public void add(@PathVariable("abc") int id){ System.out.println("获取数据"+id); } @PostMapping("/user/{abc}") public void delete(@PathVariable("abc") int id){ System.out.println("新建数据"+id); }
@PutMapping("/user/{abc}") public void update(@PathVariable("abc") int id){ System.out.println("更新数据"+id); }
@DeleteMapping("/user/{abc}") public void newRes(@PathVariable("abc") int id){ System.out.println("删除数据"+id); }
注意事项:使用restful时,web.xml中url-pattern必须是/,不能是其他的,那么这样又会拦截一些需要的静态资源,所以需要在springmvc.xml中配置来加载静态资源:
mapping代表映射文件目录,**表示当前以及子类的所有文件夹,*只是当前文件夹。
<mvc:resources mapping="/js/**" location="/js/"></mvc:resources> <mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
10.springmvc拦截器
10.1拦截器的作用
springmvc提供拦截器实现对Handler进行面向切面编程,可以Handler执行之前、之后、之中添加代码,这种方式就是切面编程。可以拦截静态资源和请求的接口,不能拦截jsp页面。需要使用过滤器来拦截jsp页面。
10.2使用拦截器步骤
1)定义一个类实现HanlderInterceptor接口,此代码作为参考示例,后面会添加业务逻辑
package com.zxh.config;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class MyIntercept implements HandlerInterceptor {
//preHandle:在Handler执行之前调用
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("pre...");
//return true代表放行
//return flase代表拦截
return true;
}
//postHandle:在Handler中方法执行一半时调用(return ModelAndView前),可以更改跳转的视图
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("post...");
}
//afterCompletion:在Handler执行完毕之后调用,可以用于异常的处理
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("after...");
}
}
2)在springmvc.xml中配置拦截器
<!--配置拦截器-->
<mvc:interceptors>
<!--设置一个拦截路径,也可以写多个 <mvc:interceptor>拦截多个路径-->
<mvc:interceptor>
<!--path里面是要拦截的路径,/**表示拦截所有的请求-->
<mvc:mapping path="/**"/>
<!--把Myintercept交给springmvc管理-->
<bean class="com.zxh.config.MyIntercept"></bean>
</mvc:interceptor>
</mvc:interceptors>
11.springmvc过滤器
11.过滤器的作用
springmvc过滤器可以过滤所有的请求,范围大,但有局限性。获取不到session的值。
11.2使用拦截器步骤
1)定义一个类实现HanlderFilter接口,此代码作为参考示例,后面会添加业务逻辑
package com.zxh.config; import javax.servlet.*; import java.io.IOException; public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
2)在web.xml中配置
<filter> <filter-name>loginFilter</filter-name> <filter-class>com.zxh.config.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>loginFilter</filter-name> <url-pattern>/</url-pattern> </filter-mapping>
11.3过滤器与拦截的差异
相同点:都可以拦截请求,过滤请求,应用了过滤器(责任链)设计模式。。
不同点:filter范围比较大,在web.xml中配置;intercepter范围比较小,在springmvc.xml中配置。在进入springmvc处理之前会先处理web.xml的配置,因此会先进入过滤器,故此时获取不到session中的值,只能是拦截器中获取。
13、SSM框架整合
dao层:mybatis+spring
service层:spring
controller层:springmvc+spring
整合步骤:
- 新建一个web项目,在WEB-INF目录下创建一个lib目录,为它添加包依赖
- 导入所有的jar包到lib中
- 在根目录下新建一个config目录,设置为资源目录,用于存放配置文件
- 把所有需要的配置文件放到config目录中,修改部分配置
- 在web.xml配置加载spring容器
- 新建所有的类和接口进行测试