1、SpringMVC
springmvc 属于 spring 的一部分。
1.1、MVC
Model:模型层
- 业务处理:Service
- 数据库持久层:Dao
- 实体类:JavaBean,pojo,entity
View:视图层(Html,Jsp)
Controller:控制层(Servlet)
1.2、相关依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
</dependency>
</dependencies>
1.3、执行流程
1.4、显示开发
如果是创建普通maven项目,需要为项目添加webapp支持。
1、配置 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">
<!--注册DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--关联springmvc的配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<!--启动级别1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--/:匹配所有请求(不包括.jsp)-->
<!--/*:匹配所有请求(包括.jsp)-->
<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>
2、配置 spring-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--处理器映射器-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--将controller注入到spring容器中-->
<bean id="/hello" class="com.controller.HelloController"/>
</beans>
3、前端页面
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="/hello">
<input type="submit">
</form>
</body>
</html>
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
4、controller
import org.springframework.web.servlet.mvc.Controller;
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response){
ModelAndView mv = new ModelAndView();
//业务代码
String s = "aaa";
mv.addObject("msg",s); //封装
//视图跳转
mv.setViewName("hello");
return mv;
}
}
5、配置 Tomcat
6、运行测试
7、注意点
如果404
- 在项目结构(project structure)中的 Artifacts → WEB-INF 下新建 lib 文件夹,并且导入相关依赖。
- 考虑静态资源过滤问题,在 pom.xml 添加
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
2、注解开发
2.1、开发
1、配置 web.xml,与显示开发相同
2、配置 spring-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
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--自动扫描包,让指定包下的注解生效,由IOC容器管理-->
<context:component-scan base-package="com.controller"/>
<!--让SpringMVC不处理静态资源,使css,js等文件不走视图解析器-->
<mvc:default-servlet-handler/>
<!--支持mvc注解驱动,代替映射器和适配器-->
<mvc:annotation-driven/>
<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
3、前端页面,与显示开发相同
4、controller
@Controller //相当于在spring-servlet.xml中配置beans
public class HelloController {
@RequestMapping("/hello") //前后端交互接口
public String hello(Model model){
//封装数据
model.addAttribute("msg","hello");
return "hello"; //视图解析器处理返回的字符串,拼接为路径找到对应文件进行渲染
}
}
5、配置 Tomcat
6、运行测试
2.2、控制器
- @Controller
- 提供访问应用程序的行为,使用接口(1.4)或注解(2.1)定义实现。
- 解析用户请求并转化为模型
2.3、请求映射器
- @RequestMapping
- 用于映射 url 到控制器。
- 可以加在方法上面,也可以加在类上面。
3、RestFul
传统方式操作资源:通过不同的参数来实现不同的效果!方法单一,post 和get
- http://127.0.0.1/item/queryltem.action?id=1 查询GET
- http://127.0.0.1/item/saveltem.action 新增POST
- http://127.0.0.1/item/updateltem.action 更新POST
- http://127.0.0.1/item/deleteltem.action?id=1 删除GET或POST
使用 RestFul 操作资源:可以通过不同的请求方式来实现不同的效果!如下:请求地址一
样,但是功能可以不同!
- http://127.0.0.1/item/1 查询GET
- http://127.0.0.1item 新增POST
- http://127.0.0.1item 更新PUT
- http://127.0.0.1/item/1 删除DELETE
新建 RestFulController
//传统访问的链接是http://localhost:8080/add?a=3
//RestFul风格访问的链接最后会是http://localhost:8080/add/3
@Controller
public class RestFulController {
@GetMapping("/add/{a}")
public String test(@PathVariable int a, Model model) {
model.addAttribute("msg", "add"+a);
return "hello";
}
}
4、重定向和转发
SpringMVC可以不使用视图解析器使用转发,但是要写完整路径;重定向不需要视图解析器。
//转发一
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","hello");
return "/WEB-INF/jsp/hello.jsp";
}
}
//转发二
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","hello");
return "forward:/WEB-INF/jsp/hello.jsp";
}
}
//重定向
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("msg","hello");
return "redirect:/index.jsp";
}
}
5、数据处理
5.1、数据接收
1、提交的域名称和处理方法的参数名一致
提交数据 : http://localhost:8080/hello?name=abc
处理方法 :
@RequestMapping("/hello")
public String hello(String name){
System.out.println(name);
return "hello";
}
后台输出 : abc
2、提交的域名称和处理方法的参数名不一致
提交数据 : http://localhost:8080/hello?username=abc
处理方法 :
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
System.out.println(name);
return "hello";
}
后台输出 : abc
3、提交的是一个对象
要求提交的表单域和对象的属性名一致 , 参数使用对象即可
1、实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private int age;
}
2、提交数据 : http://localhost:8080/mvc04/user?name=abc&id=1&age=15
3、处理方法 :
@RequestMapping("/user")
public String user(User user){
System.out.println(user);
return "hello";
}
后台输出 : User { id=1, name=‘abc’, age=15 }
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null。
5.2、数据返回前端
1、通过ModelAndView
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws Exception {
//返回一个模型视图对象
ModelAndView mv = new ModelAndView();
mv.addObject("msg","hello");
mv.setViewName("test");
return mv;
}
}
2、通过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";
}
3、 通过Model
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, Model model){
//封装要显示到视图中的数据
//相当于req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
6、拦截器
拦截器是AOP思想的具体应用,会在事务处理前和处理后进行操作。
过滤器
- servlet规范中的一部分,任何java web工程都可以使用。
- 在url-pattern中配置了/*之后,可以对所有要访问的资源进行拦截。
拦截器
- 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用。
- 拦截器只会拦截访问的控制器方法, 效率更高。
6.1、实现
1、使用拦截器需要实现接口
public class MyInterceptor implements HandlerInterceptor {
//在请求处理的方法之前执行
//如果返回true执行下一个拦截器
//如果返回false就不执行下一个拦截器
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("------------处理前------------");
return true;
}
//在请求处理方法执行之后执行
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("------------处理后------------");
}
//在dispatcherServlet处理后执行,做清理工作.
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("------------清理------------");
}
}
2、在 applicationContext.xml 中配置
<!--关于拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<!--bean配置的就是拦截器-->
<bean class="com.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
6.2、实践
实现一个登录功能,登录成功后进入用户页面,未登录进入用户页面跳转登录页面,登录后注销再次未登录进入用户页面跳转登录页面。
1、Controller
@Controller
public class LoginController {
//进入登录页面
@RequestMapping("/toLogin")
public String toLogin(){
return "login";
}
//提交登录
@RequestMapping("/login")
public String login(String name, String pwd, HttpSession session){
//设置session值作为是否登录标志
String s = name+pwd;
session.setAttribute("loginInfo",s);
return "main";
}
//进入用户页面
@RequestMapping("/main")
public String main(){
return "main";
}
//注销
@RequestMapping("/logout")
public String logout(HttpSession session){
//移除session中的值
session.removeAttribute("loginInfo");
return "login";
}
}
2、Interceptor
public class MyInterceptor implements HandlerInterceptor {
//在执行前进行拦截检测
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取当前session
HttpSession session = request.getSession();
//设置允许任意通过的请求
//允许进入登录页面
if (request.getRequestURI().contains("toLogin")){
return true;
}
//允许登录
if (request.getRequestURI().contains("login")){
return true;
}
//除以上页面,所有请求将转发至登录页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
3、在 applicationContext.xml 中配置
<!--关于拦截器的配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--/** 包括路径及其子路径-->
<!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截-->
<!--/admin/** 拦截的是/admin/下的所有-->
<mvc:mapping path="/**"/>
<!--bean配置的就是拦截器-->
<bean class="com.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
4、测试
- 登录后进入用户页面,成功
- 未登录进入用户页面,转发至登录页面
- 登录后登出再进入用户页面,转发至登录页面
- 登录后未登出返回登录页面进入用户页面,成功
7、文件上传和下载
7.1、文件上传
1、导入相关依赖
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
2、配置
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上传文件大小上限,单位为字节(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
3、前端
前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
</body>
</html>
4、后端
package com.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
@RestController
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;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
}
5、采用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 "redirect:/index.jsp";
}
7.2、文件下载
1、后端
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response ,HttpServletRequest request) throws Exception{
//要下载的图片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "aaa.jpg";
//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 null;
}
2、前端
<a href="/download">点击下载</a>
se 响应头
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 null;
}
2、前端
```xml
<a href="/download">点击下载</a>