SpringMvc的简单使用
1、什么是MVC
- MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。
- 是将业务逻辑、数据、显示分离的方法来组织代码。
- MVC主要作用是降低了视图与业务逻辑间的双向偶合。
- MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。
**Model(模型):**数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
**View(视图):**负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
**Controller(控制器):**接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。
2、什么是SpringMVC
2.1为什么要学习SpringMVC?
Spring MVC的特点:
- 轻量级,简单易学
- 高效 , 基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约定优于配置
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简洁灵活
2.2配置SpringMvc的环境
-
引入依赖
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.19</version> </dependency> </dependencies>
-
替换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"> </web-app>
-
在web.xml上注册Dispatcher Servlet
<?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>dispactherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <!--classpath:表示编译后的路径--> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dispactherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
创建配置文件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: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 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.zzs.controller"/> </beans>
-
创建controller类
@Controller //添加注解,该注解标记该类为处理层类 public class HelloController { @RequestMapping(value = "/hello") //把请求路径映射到该方法上。 public String hello01(){ System.out.println("业务处理"); return "hello01.jsp"; //返回一个响应页面 } }
-
创建hello01.jsp页面,添加项目,启动tomcat,在网页上输入hello即可进入hello01.jsp页面。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>hello</title> </head> <body> ${msg} </body> </html>
2.3 controller接受请求参数
-
接收少量参数
@RequestMapping("delete") public String delete(int id){ System.out.println("根据id删除信息"+id); return "index.jsp"; }
-
接受大量参数
-
创建一个实体类,用来提交一个对象
@Data @AllArgsConstructor @NoArgsConstructor public class User { private String name; private String password; private String address; }
-
在web.xml文件中配置springmvc提供的编码过滤器
<filter> <filter-name>encodingfilter</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>encodingfilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
-
处理方法
@RequestMapping("/user") public String user(User user){ System.out.println(user); return "hello"; }
说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则就是null
3.处理静态资源
-
如果页面有图片等静态资源,需要在springmvc中进行放行
<!--放行静态资源:哪些资源为静态资源。css img js html--> <mvc:default-servlet-handler/>
-
如果页面有时间数据,在创建实体类中需要添加注解
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String address; @DateTimeFormat(pattern = "yyyy-MM-dd") private Date date; }
3. 如何把controller数据返回到网页并回显。
1、将springmvc中如何保存数据到网页上。
@Controller
@SessionAttributes(value = {"user","user2"}) //设置哪些model的key在session范围
public class HelloController02 {
@RequestMapping("/list")
public String list(HttpServletRequest request){
//查询到一个学生信息。
Student student=new Student(1,"张三","郑州",new Date());
//可以保存到request中,同一个请求
request.setAttribute("s",student);
return "list.jsp"; //转发
}
2、重定向跳转
@RequestMapping("list5")
public String list5(){
System.out.println("!!!!!!!!!!!!!!!!!");
return "redirect:list.jsp"; //redirect:重定向跳转标注
}
4、springmvc返回json数据
1、添加依赖
<!--jackson依赖 可以把java对象转换为json对象-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.2.2</version>
</dependency>
2、在controller返回的数据类型变成javabean对象。
@RequestMapping("json01")
@ResponseBody //作用:把java对象转换为json对象
public List<Student> json01(){ //这里返回的类型为java对象。 之前都是返回字符串
List<Student> list=new ArrayList<Student>();
list.add(new Student(1,"张三","北京",new Date()));
list.add(new Student(2,"李四","郑州",new Date()));
list.add(new Student(3,"王五","上海",new Date()));
list.add(new Student(4,"赵六","南京",new Date()));
return list; //当中json
}
3、页面返回时间为毫秒,要想显示时间格式需要添加注解
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String address;
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date date;
}
5、springmvc拦截器
过滤器: 过滤掉某些资源,拦截器只会拦截controller层的资源路径。如何使用拦截器:
-
创建一个类并实现HandlerInterceptor
public class MyInterceptor implements HandlerInterceptor { //拦截器的处理方法。 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("经过了该拦截器"); return true;//true:表示拦截器放行 false:不放行 } }
-
把该类注册到springmvc配置文件上。
<!--拦截器的配置--> <mvc:interceptors> <mvc:interceptor> <!--mapping:哪些路径需要经过拦截器 /**: 表示n层路径 /*:表示一层路径 --> <mvc:mapping path="/**"/> <!--exclude-mapping:设置不经过该拦截的路径--> <mvc:exclude-mapping path="/list2"/> <mvc:exclude-mapping path="/list3"/> <!--bean表示你自定义的拦截器类路径--> <bean class="com.ykq.interceptor.MyInterceptor"/> </mvc:interceptor> </mvc:interceptors
6、文件上传
6.1文件上传到本地服务器。
-
添加文件上传依赖
<!--文件上传的依赖--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
-
创建文件上传页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <body> <h2>Hello World!</h2> <form method="post" action="upload03" enctype="multipart/form-data"> <input type="file" name="myfile"/> <input type="submit" value="提交"> </form> </body> </html>
-
在springmvc中配置文件上传解析器
<!-- id的名称必须叫multipartResolver --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--这里的单位为字节10M*1024K*1024--> <property name="maxUploadSize" value="10485760"/> </bean>
-
创建接口进行测试
@Controller public class LoginController { @RequestMapping("upload") @ResponseBody public Map upload(MultipartFile file, HttpServletRequest request) { try { String path = request.getSession().getServletContext().getRealPath("upload"); File file1 = new File(path); if (!file1.exists()){ file1.mkdirs(); } String name = UUID.randomUUID().toString().replace("-","")+file.getOriginalFilename(); File target = new File(path+"/"+name); file.transferTo(target); Map map =new HashMap(); map.put("code",2000); map.put("msg","上传成功"); map.put("data","http://localhost:8080/untitled_war/upload/"+name); return map; } catch (IOException e) { e.printStackTrace(); } Map map =new HashMap(); map.put("code",5000); map.put("msg","上传失败"); return map; } }
6.2将文件上传到网络服务器
-
申请阿里云服务器
-
引入依赖
<!--文件上传的依赖--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
-
编写上传页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <!--引入element得css样式--> <link type="text/css" rel="stylesheet" href="css/index.css"/> <!--引入vue得js文件 这个必须在element之前引入--> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/qs.min.js"></script> <script type="text/javascript" src="js/axios.min.js"></script> <!--element得js文件--> <script type="text/javascript" src="js/index.js"></script> </head> <body> <div id="app"> <%--action:文件上传的路径--%> <el-form label-width="80px" :model="userForm"> <el-form-item label="头像"> <el-upload class="avatar-uploader" action="/untitled_war/uploadAvatar" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"> <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload> </el-form-item> <el-form-item label="账号"> <el-input v-model="userForm.name"></el-input> </el-form-item> <el-form-item label="密码"> <el-input v-model="userForm.password"></el-input> </el-form-item> <el-form-item label="地址"> <el-input v-model="userForm.address"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit">提交</el-button> </el-form-item> </el-form> </div> </body> <script> var app=new Vue({ el:"#app", data:{ imageUrl:"", userForm:{} }, methods:{ //上传成功后触发的方法 handleAvatarSuccess(res, file) { this.imageUrl=res.data; // 为表单回显头像地址 this.userForm.avatarUrl=this.imageUrl; }, //上传前触发的方法 beforeAvatarUpload(file) { /*const isJPG = file.type === 'image/jpeg';*/ const isLt2M = file.size / 1024 / 1024 < 2; /* if (!isJPG) { this.$message.error('上传头像图片只能是 JPG 格式!'); }*/ if (!isLt2M) { this.$message.error('上传头像图片大小不能超过 2MB!'); } return isLt2M; }, // 提交功能 onSubmit(){ axios.post("/untitled_war/addUser",this.userForm).then(function (res){ console.log(res); }) } } }) </script> <style> .avatar-uploader .el-upload { border: 1px dashed #d9d9d9; border-radius: 6px; cursor: pointer; position: relative; overflow: hidden; } .avatar-uploader .el-upload:hover { border-color: #409EFF; } .avatar-uploader-icon { font-size: 28px; color: #8c939d; width: 178px; height: 178px; line-height: 178px; text-align: center; } .avatar { width: 178px; height: 178px; display: block; } </style> </html>
-
编写上传代码
public class OSSUtil { public static String upload(MultipartFile myfile){ // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。 String endpoint = "oss-cn-hangzhou.aliyuncs.com"; // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。 String accessKeyId = "自己的秘钥ID"; String accessKeySecret = "秘钥密码"; // 填写Bucket名称,例如examplebucket。 String bucketName = "填写自己的Bucket名称"; // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。 String objectName = filmName(myfile); // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); try { InputStream inputStream = myfile.getInputStream(); // 创建PutObject请求。 ossClient.putObject(bucketName, objectName, inputStream); } catch (Exception oe) { } finally { if (ossClient != null) { ossClient.shutdown(); } } // //https://zengzs.oss-cn-hangzhou.aliyuncs.com/2022/5/10b2edbd18f2e646d8ab97ca081881c5d81.jpeg String url = "https://"+bucketName+"."+endpoint+"/"+objectName; return url; } private static String filmName(MultipartFile myfile){ Calendar calendar = Calendar.getInstance(); String name= calendar.get(Calendar.YEAR)+"/"+(calendar.get(Calendar.MONTH)+1)+"/"+calendar.get(Calendar.DATE)+"/" + UUID.randomUUID().toString().replace("-","")+myfile.getOriginalFilename(); return name; } }
7、各种注解的作用
@RestController----类上等价于 @COntroller+@ResponseBody
该注解下所有的方法都是返回json数据
@RequestMapping: 作用: 把请求路径映射到响应的方法上。
@RequestParam(value = "u"):设置你接受的请求参数名。查询参数
@RequestMapping(value = "/addUser",method = RequestMethod.POST)
method:表示该接口接受的请求方式.不设置可以接受任意请求方式。
@GetMapping("addUser"):表示只接受get提交方式的请求
@RequestBody:把请求的json数据转换为java对象。从前端到后端
@ResponseBody:把java转换为json数据 从后端转前端