JavaEE结构包括四层,从上到下分别是应用层、Web层、业务层、持久层。SpringMVC是Web层的框架
1.什么是SpringMVC
springmvc属于spring家族的一个模块 ,Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦, 把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
MVC是指:
Controller:控制器,负责处理请求和响应
View:视图
Model:视图展示所需的数据
2.SpringMVC框架图
具体流程:
- 游览器发送求到前端控制器(DispatcherServlet),但控制器自身不会处理而是交给其他解析器处理,自身只是对全局的控制。
- DispatcherServlet——>HandlerMapping,前端控制器请求映射器查找Handler,可以根据xml配置、注解进行查找
- 处理器映射器HandlerMapping向前端控制器返回Handler
- 前端控制器调用处理器适配器去执行Handler
- 处理器适配器去执行Handler
- Handler执行完成给适配器返回ModelAndView
- 处理器适配器向前端控制器返回ModelAndView,ModelAndView是springmvc框架的一个底层对象,包括 Model和view
- 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
- 视图解析器向前端控制器返回View
- 前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域
- 前端控制器向用户响应结果
3.SpringMVC实现方式
前提:配置springmvc.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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
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">
<!--开启包扫描,全注解方式-->
<context:component-scan base-package="com.hqyj.gyq.controller"></context:component-scan>
<!--开启mvc的注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--id:配置访问路径,第②③种方式-->
<!-- <bean id="/hello" class="com.hqyj.gyq.controller.HelloWorldController"></bean>-->
<!-- <bean id="/hello1" class="com.hqyj.gyq.controller.FirstController"></bean>-->
<!-- 静态资源放行 要用单标签形式,-->
<mvc:default-servlet-handler/>
<!--配置mvc的视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="../view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<!--配置上传文件的大小-->
<property name="maxUploadSize" value="5242440"></property>
</bean>
</beans>
①第一种实现Controller接口
package com.hqyj.gyq.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 HelloWorldController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp)
throws Exception {
ModelAndView mv = new ModelAndView();
// 设置视图
mv.setViewName("/jsp/show.jsp");
// 设置model
mv.addObject("name","zs");
return mv;
}
}
②实现HttpRequestHandler接口
package com.hqyj.gyq.controller;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class FirstController implements HttpRequestHandler {
/*跟之前操作servlet是一样的*/
@Override
public void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name1","ls");
// req.getRequestDispatcher("/jsp/show1.jsp").forward(req,resp);
resp.sendRedirect("/jsp/show1.jsp");
}
}
③全注解
package com.hqyj.gyq.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 全注解开发
* 每一个请求对应到的一个方法
*/
@Controller
public class SystemController {
@RequestMapping("/sys/login")
public String login(){
System.out.println("login.......");
// 默认是转发
return "../jsp/index.jsp";
}
@RequestMapping("/sys/register")
public String register(){
System.out.println("register.......");
// 默认是转发
return "../jsp/login.jsp";
}
}
4.前后端参数传递
①普通数据传输
springmvc获取页面传参:页面传递的参数名对应到方法中的参数名,会自动接收参数值
使用注解:
@Controller:表明控制类
@RequestMapping("路径名")
package com.hqyj.cq.controller;
import com.hqyj.cq.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/user")
public class SystemController {
@RequestMapping("/login")
public void login(String userName,String userPwd){
// req.getParamter("userName");
System.out.println(userName+"||"+userPwd);
}
@RequestMapping("/login1")
// @RequestParam("username")解决页面传递的参数名和方法中接收的参数名不一致的情况,其中username:页面传递的参数名
public void login1(@RequestParam("username") String userName, String userPwd){
// req.getParamter("userName");
System.out.println(userName+"||"+userPwd);
}
/**
* 如果页面传递多个参数,则可以使用对象接收
// * @param user
*/
@RequestMapping("/register")
public void register(User user){
System.out.println(user);
}
}
②json数据传输
使用注解:
@ResponseBody:将java对象转为json格式的数据
@PostMapping("路径名") 和@GetMapping("路径")都是处理方法的路径,只是有post和get方法的区别
后端controller层
package com.hqyj.cq.controller;
import com.hqyj.cq.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/queryUserById")
// 返回json格式的数据
@ResponseBody
public User queryUserById(Integer userId) {
System.out.println(userId);
// 模拟从数据库中查询出的用户
User user = new User(1,"zs",23,"324342");
return user;
}
@PostMapping("/login")
// 返回json格式的数据
@ResponseBody
public String login(User user){
//假设数据库中有个用户名为zs,密码为:123
if(user.getUserName().equals("zs")&&user.getUserPwd().equals("123")){
System.out.println("登录成功!");
return "success";
}else {//账号密码输入错误
System.out.println("登录失败!");
return "fail";
}
}
/**
* @RequestBody:接收页面传递过来的json格式化的字符串,需要用post请求
// * @param user
* @return
*/
@PostMapping("/login1")
@ResponseBody
public String login1(@RequestBody User user){
//假设数据库中有个用户名为zs,密码为:123
if(user.getUserName().equals("zs")&&user.getUserPwd().equals("123")){
System.out.println("登录成功!");
return "success";
}else {//账号密码输入错误
System.out.println("登录失败!");
return "fail";
}
}
}
package com.hqyj.cq.entity;
public class User {
private Integer userId;
private String userName;
private Integer userAge;
private String userPwd;
public User() {
}
public User(Integer userId, String userName, Integer userAge, String userPwd) {
this.userId = userId;
this.userName = userName;
this.userAge = userAge;
this.userPwd = userPwd;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getUserAge() {
return userAge;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
}
前端jsp文件
当用一个对象接收json数据时要使用
contentType:"application/json",
//contentType:浏览器告诉服务器传递的参数的类型,application/json:序列化后的json字符串
data:JSON.stringify(类对象),
//将js对象转化为json格式的字符串
<%--
Created by IntelliJ IDEA.
User: 86139
Date: 2022/9/6
Time: 9:29
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
<script src="../static/js/jquery-1.11.3.min.js"></script>
</head>
<body>
<span>用户名:</span><input type="text" id="user_name" name="userName">
<br>
<span>密码:</span><input type="password" id="user_pwd" name="userPwd">
<br>
<span id="mess1" style="color: red"></span>
<br>
<input type="button" id="login" value="登录">
<hr>
<span>用户名:</span><input type="text" id="user_name1" name="userName">
<br>
<span>密码:</span><input type="password" id="user_pwd1" name="userPwd">
<br>
<span id="mess" style="color: red"></span>
<br>
<input type="button" id="login1" value="登录">
<script>
$("#login").click(function () {
var username = $("#user_name").val();
var userpwd = $("#user_pwd").val();
$.ajax({
url:"../user/login",
type:"POST",
dataType:"text",
data:{"userName":username,"userPwd":userpwd},
success:function (data) {
if(data=="success"){
// window.location.href="index.jsp";
window.location.href="../page/index";
}else {//账号或者密码输入错误
$("#mess").html("账号或密码错误!");
}
},
error:function (e) {
alert("服务器出错!")
}
});
});
//使用一个对象接收数据
$("#login1").click(function () {
var username = $("#user_name1").val();
var userpwd = $("#user_pwd1").val();
//封装成一个js对象
var user = {userName:username,userPwd:userpwd};
$.ajax({
url:"../user/login1",
type:"POST",
contentType:"application/json",//contentType:浏览器告诉服务器传递的参数的类型,application/json:序列化后的json字符串
dataType:"text",//服务器响应回的数据类型
data:JSON.stringify(user),//将js对象转化为json格式的字符串
success:function (data) {
if(data=="success"){
// window.location.href="index.jsp";
window.location.href="../page/index";
}else {//账号或者密码输入错误
$("#mess").html("账号或密码错误!");
}
},
error:function (e) {
alert("服务器出错!")
}
});
});
</script>
</body>
</html>
5.其他要点
①Restful风格:
Restful就是一个资源定位、资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
可以通过不同的请求方式来实现不同的效果!
如:请求地址一样,但是功能可以不同!
http://localhost:8080/springMvc_j220701_day02/people/1 (GET 查询)
http://localhost:8080/springMvc_j220701_day02/people/1 (DELETE 删除)
要使用@PathVariable注解:
通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中:URL 中的 {xxx} 占位符可以通过@PathVariable(“xxx“) 绑定到操作方法的入参中
controller层代码
package com.hqyj.cq.controller;
import com.hqyj.cq.entity.People;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/people")
public class PeopleController {
// 模拟查询
@GetMapping("/{pId}")
@ResponseBody
public People queryPeople(@PathVariable("pId") Integer pId){
System.out.println(pId + "查询");
return new People();
}
// 模拟删除
@DeleteMapping("/{pId}")
@ResponseBody
public People deletePeopleById(@PathVariable("pId") Integer pId){
System.out.println(pId+"删除");
return new People();
}
}
前端jsp文件
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2022/9/6
Time: 16:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<script src="../static/js/jquery-1.11.3.min.js"></script>
</head>
<body>
<button type="button" onclick="find()">查询</button>
<button type="button" onclick="deletePeople()">删除</button>
<script>
function find() {
$.ajax({
url:"../people/1",
type:"GET",
dataType:"json",
success:function (data) {
console.log(data)
}
})
}
function deletePeople() {
$.ajax({
url:"../people/1",
type:"DELETE",
dataType:"json",
success:function (data) {
console.log(data);
}
});
}
</script>
</body>
</html>
②文件上传和下载
直接拿来用
首先配置springmvc.xml文件
<!-- 文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<!--配置上传文件的大小-->
<property name="maxUploadSize" value="5242440"></property>
controller层代码
package com.hqyj.cq.controller;
import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
@Controller
@RequestMapping("/file")
public class FileController {
@PostMapping("/upload")
@ResponseBody
public String upload(MultipartFile file, HttpServletRequest request) throws IOException {
//获取工程目录。
String path = request.getSession().getServletContext().getRealPath("upload");
System.out.println(path);
// 获取文件名
String fileName = file.getOriginalFilename();
System.out.println(fileName);
File dir = new File(path,fileName);
if(!dir.exists()){
dir.mkdirs();
}
file.transferTo(dir);
return "success";
}
@RequestMapping("/download")
public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception{
String path = request.getSession().getServletContext().getRealPath("upload");
// 创建该文件对象
File file = new File(path+File.separator+filename);
// 对文件名编码,防止中文文件乱码
filename = this.getFilename(request, filename);
// 设置响应头
HttpHeaders headers = new HttpHeaders();
// 通知浏览器以下载的方式打开文件
headers.setContentDispositionFormData("attachment", filename);
// 定义以流的形式下载返回文件数据
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 使用Sring MVC框架的ResponseEntity对象封装返回下载数据
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
headers, HttpStatus.OK);
}
/**
* 根据浏览器的不同进行编码设置,返回编码后的文件名
*/
public String getFilename(HttpServletRequest request,
String filename) throws Exception {
// IE不同版本User-Agent中出现的关键词
String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
// 获取请求头代理信息
String userAgent = request.getHeader("User-Agent");
for (String keyWord : IEBrowserKeyWords) {
if (userAgent.contains(keyWord)) {
//IE内核浏览器,统一为UTF-8编码显示
return URLEncoder.encode(filename, "UTF-8");
}
}
//火狐等其它浏览器统一为ISO-8859-1编码显示
return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
}
}
前端jsp代码
<%--
Created by IntelliJ IDEA.
User: Lenovo
Date: 2022/9/6
Time: 16:55
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--
method="post"
enctype="multipart/form-data"
--%>
<form action="../file/upload"method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="file" width="120px">
<input type="submit" value="上传">
</form>
<br>
<a href="../file/download?filename=2019133.doc">下载</a>
</body>
</html>