SpringMVC
一、SpringMVC介绍
1.什么是MVC
是一种软件架构的思想,将软件按照模型、视图、控制器来划分
- M:Model,模型层,指工程中的JavaBean,作用是处理数据
- JavaBean
- 一类称为实体类Bean:专门存储业务数据的,如 Student、User 等
- 一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。
- V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据
- C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器
MVC工作流程: 用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器
2.什么是SpringMVC
是Spring的一个后续产品,是Spring的一个子项目
SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选。
三层架构:表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet
3.SpringMVC的优点
- 轻量级,基于MVC框架
- 易上手,易理解,功能强大
- 具备IOC和AOP
- 完全基于注解开发
二、工程创建
1.开发环境
idea:2019.3.5
tomcat:9.0.59
Spring:5.3.22
Maven:3.6.1
2.基于注解的SpringMVC框架开发步骤总结
- 新建项目(可以直接选择webapp的模板)
- 补全目录
- 修改pom.xml,添加SpringMVC和Servlet依赖
- 添加springmvc.xml配置文件,指定包扫描,添加视图解析器
- 删除web.xml文件,新建web.xml(版本过低有些功能不支持)
- web.xml中注册springmvc框架
- webapp下新建admin目录,在目录下新建main.jsp页面,删除index.jsp再添加index.jsp页面
- 开发控制器(Servlet)
- 添加tomcat测试功能
实例
DemoAction.java
package com.xust.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class DemoAction {
@RequestMapping("/demo.action")
public String demo(){
System.out.println("服务器被访问到了。。。。。");
return "main"; //直接跳到/admin/mian.jsp页面
}
}
springmvc.xml
web.xml
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
springmvc
*.action
pom.xml
4.0.0
com.xust
spring_001_demo
1.0
war
UTF-8
1.8
1.8
junit
junit
4.11
test
org.springframework
spring-webmvc
5.3.1
javax.servlet
javax.servlet-api
3.1.0
provided
src/main/java
**/*.xml
**/*.properties
src/main/resources
**/*.xml
**/*.properties
index.jsp
Title
访问服务器
三、RequestMapping注解
将请求和处理请求的控制器方法关联起来,建立映射关系。
SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。
- 此注解加在方法前,可以为此方法注册一个可以访问的名称(路径)。
- 此注解加在类前,相当于虚拟路径,对不同类进行区分
如:我在前面例子中类名前加@RequestMapping(“/zar”),那么index.jsp中就要改为
${pageContext.request.contextPath}/zar/demo.action
- 此注解可区分Get请求和Post请求
区分请求举例
package com.xust.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class ReqAction {
@RequestMapping(value = "/req.action",method = RequestMethod.GET)
public String req(){
System.out.println("我是处理get请求的。。。。。。。。。。");
return "main";
}
@RequestMapping(value = "/req.action",method = RequestMethod.POST)
public String req1(){
System.out.println("我是处理post请求的。。。。。。。。。。");
return "main";
}
}
四、五种数据提交方式的优化
1.单个数据提交
自动注入并且类型转换
姓名:
年龄:
package com.xust.controller;
import com.xust.Users;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class DataSubmitAction {
@RequestMapping("/one.action")
public String one(String myname,int myage){ //自动注入并且类型转换
System.out.println("myname="+myname+",myage="+(myage+100));
return "main";
}
}
2.对象封装提交数据
保证jsp中的name和类中的成员变量名称相同
在提交请求中,保证请求参数的名称与实体类中成员变量名称一致,则可以自动提交数据,自动类型转换,自动封装数据到对象中。
2.对象封装数据提交
姓名:
年龄:
package com.xust;
public class Users {
private String name;
private int age;
public Users(){}
public Users(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Users{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.xust.controller;
import com.xust.Users;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class DataSubmitAction {
@RequestMapping("/two.action")
public String two(Users u){
System.out.println(u);
return "main";
}
}
3.动态占位符提交
仅限于超链接或地址栏提交数据
一杠一值,一杠一大括号,使用注解来解析
3.动态占位符提交
动态提交
package com.xust.controller;
import com.xust.Users;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class DataSubmitAction {
@RequestMapping("/three/{name}/{age}.action")
public String three(
@PathVariable
String name,
@PathVariable
int age){
System.out.println("name="+name+",age="+(age+100));
return "main";
}
}
//如果@RequestMapping中是{uname},下边可以用@PathVariable("uname)
4.映射名称不一致
提交请求参数与action方法的形参名称不一致,使用注解@RequestParam来解析
4.参数名称不一致
姓名:
年龄:
package com.xust.controller;
import com.xust.Users;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class DataSubmitAction {
@RequestMapping("/four.action")
public String four(
@RequestParam("name")
String uname,
@RequestParam("age")
int uage){
System.out.println("uname="+uname+",uage="+(uage+100));
return "main";
}
}
5.手工提取数据
5.手工提取数据
姓名:
年龄:
package com.xust.controller;
import com.xust.Users;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
public class DataSubmitAction {
@RequestMapping("/five.action")
public String five(HttpServletRequest request){
String name=request.getParameter("name");
int age=Integer.parseInt(request.getParameter("age"));
System.out.println("name="+name+",age="+(age+100));
return "main";
}
}
五、中文编码过滤器配置
在web.xml最前面加如下配置
encode
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceRequestEncoding
true
forceResponseEncoding
true
encode
/*
六、action方法返回值
- String:客户端资源地址,自动拼接前缀和后缀,还可以屏蔽自动拼接字符串,可以指定返回路径。
- Object:返回json格式对象,自动将对象或集合转为json,使用jackson工具进行转换,必须添加jackson依赖,一般用于ajax请求。
- void:无返回值,一般用于ajax请求。
- 基本数据类型:用于ajax请求。
- ModelAndView:返回数据和视图对象,现在用的很少。
七、ajax请求返回学生集合
- 添加jackson依赖
- 在webapp目录下新建js目录,添加jQuery函数库
- 在index.jsp导入函数库
- 在action上添加注解@ResponseBody,用来处理ajax请求
- 在springmvc.xml添加注解驱动< mvc:annotationdriven/ >,它用来解析@ResponseBody注解
八、请求转发和重定向
转发可以携带数据,重定向不行
redirect和forward都可以屏蔽前后缀,但前者在重定向时使用,地址栏发生变化,后者在转发时使用,地址栏不变
1.请求转发页面(默认)
地址栏不变
1.请求转发页面(默认)
@Controller
public class StudentListAction {
@RequestMapping("/one.action")
public String one(){
return "main"; //默认是请求转发,使用视图解析器拼接前缀后缀进行页面跳转
}
}
2.请求转发action
地址栏不变
2.请求转发action
@Controller
public class StudentListAction {
@RequestMapping("/two.action")
public String two(){
//forward可以屏蔽前缀和后缀字符串的拼接
return "forward:/other.action";
}
}
@Controller
public class OtherAction {
@RequestMapping("/other.action")
public String other(){
return "main";
}
}
3.重定向页面
地址栏变为…/admin/main.jsp
3.重定向页面
@Controller
public class StudentListAction {
@RequestMapping("/three.action")
public String three(){
//redirect可以屏蔽前缀和后缀字符串的拼接
return "redirect:/admin/main.jsp";
}
}
4.重定向action
地址栏变为…/other.action
4.重定向action
@Controller
public class StudentListAction {
@RequestMapping("/four.action")
public String four(){
//redirect可以屏蔽前缀和后缀字符串的拼接
return "redirect:/other.action";
}
}
@Controller
public class OtherAction {
@RequestMapping("/other.action")
public String other(){
return "main";
}
}
九、SpringMVC默认参数类型
不需要创建,直接拿来用
- HttpServletRequest
- HttpServletResponse
- HttpSession
- Model
- Map
- ModelMap
Model、Map、ModelMap和Request一样,都使用请求作用域进行数据传递,所以服务器端的跳转必须是请求转发。
默认参数传递实例
index.jsp
访问服务器进行数据携带跳转
main.jsp
显示数据
${requestStudent}
${sessionStudent}
${modelStudent}
${mapStudent}
${modelStudent}
上面是从action传来的,从index.jsp传来的数据name为${param.name}
Student.java
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
DataAction.java
@Controller
public class DataAction {
@RequestMapping("/data.action")
public String data(HttpServletRequest request,
HttpServletResponse response,
HttpSession session,
Model model,
Map map,
ModelMap modelMap
){
//做一个数据传到main.jsp
Student stu1=new Student("张三",21);
//传递数据
request.setAttribute("requestStudent",stu1);
session.setAttribute("sessionStudent",stu1);
model.addAttribute("modelStudent",stu1);
map.put("mapStudent",stu1);
modelMap.addAttribute("modelStudent",stu1);
return "main";
}
}
十、日期处理
1.日期的提交处理
(1)单个日期处理
要使用DataTimeFormat,此注解必须搭配springmvc.xml中的
可以在方法参数上使用,也可以在类中成员变量的setXXX()方法或属性定义上使用,但是这种方法在每个用到日期类型的地方都要添加一次,比较麻烦,在下面只演示第一种情况。
日期:
@Controller
public class MyDateAction {
SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
@RequestMapping("/mydate.action")
public String mydate(
@DateTimeFormat(pattern = "yyyy-MM-dd") //将String注入给Date
Date mydate){
System.out.println(mydate);
System.out.println(sf.format(mydate));
return "show";
}
}
(2)类中全局日期处理
不使用@DateTimeFormat注解,使用@InitBinder注解,不需要绑定
@Controller
public class MyDateAction {
SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd"); //固定格式
//注册一个全局的日期处理的注解
@InitBinder
public void intiBinder(WebDataBinder dataBinder){
dataBinder.registerCustomEditor(Date.class,new CustomDateEditor(sf,true));
}
@RequestMapping("/mydate.action")
public String mydate(Date mydate){
System.out.println(mydate);
System.out.println(sf.format(mydate));
return "show";
}
}
2.日期的显示处理
如果是单个日期对象,直接转为好看的字符串进行显示
如果是List中的实体类对象的成员变量是日期类型,则必须用jstl进行显示
步骤:添加依赖Jstl,页面上导入标签库,使用标签显示数据
(1)在Json文件中日期显示
在类中成员getXXX()方法上使用注解@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”)
(2)Jsp页面的日期显示
添加依赖
jstl
jstl
1.2
jsp导入标签库
实例
集合
姓名
生日
${stu.name}
${stu.birthday}-----
public class Users {
private String name;
private Date birthday;
public Users() {
}
public Users(String name, Date birthday) {
this.name = name;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Users{" +
"name='" + name + '\'' +
", birthday=" + birthday +
'}';
}
}
@Controller
public class MyDateAction {
SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd"); //固定格式
@RequestMapping("/datelist.action")
public String datelist(HttpServletRequest request) throws ParseException {
Users u1=new Users("张三",sf.parse("2001-07-06"));
Users u2=new Users("李四",sf.parse("2001-07-07"));
Users u3=new Users("王五",sf.parse("2001-07-08"));
List list=new ArrayList<>();
list.add(u1);
list.add(u2);
list.add(u3);
request.setAttribute("list",list);
return "show";
}
}
WEB-INF目录
此目录下动态资源,不可直接访问,只能通过请求转发的方式进行访问。
去后缀
在web.xml中将 .action 改为/,访问时网址栏可省略.action后缀
登录业务实现
登录
姓名:
密码:
${msg}
@Controller
public class WebinfAction {
@RequestMapping("/showLogin")
public String showLogin(){
System.out.println("访问login.jsp");
return "login";
}
//登录的业务判断
@RequestMapping("/login")
public String login(String name, String pwd, HttpServletRequest request){
if("zar".equalsIgnoreCase(name)&&"123".equalsIgnoreCase(pwd)){
return "main";
} else{
request.setAttribute("msg","用户名或密码错误");
return "login";
}
}
}
拦截器
上面虽然已经实现了登录功能,但是通过修改地址栏可以跳过登录,安全性不够。
拦截器就是针对请求和响应添加额外的处理。在请求和响应过程中添加预处理,后处理和最终处理。
拦截器执行时机
- preHandle():请求被处理前操作
- postHandle:在请求被处理后,但结果还没有被渲染之前操作,可以改变响应结果
- afterCompletion:所有请求响应结束后执行善后工作,清理对象,关闭资源
拦截器实现的两种方式
- 继承HandlerInterceptorAdapter的父类
- 实现HandlerInterceptor接口,推荐使用实现接口的方式
拦截器实现步骤
- 改造登录方法,在session中存储用户信息,用于权限验证
- 开发拦截器功能,实现HandlerInterceptor接口,重写preHandle()方法
- 在springmvc.xml中注册拦截器
实例
登录
姓名:
密码:
${msg}
@Controller
@RequestMapping("/showMain")
public String showMain(){
System.out.println("访问main.jsp");
return "main";
}
@RequestMapping("/showLogin")
public String showLogin(){
System.out.println("访问login.jsp");
return "login";
}
//登录的业务判断
@RequestMapping("/login")
public String login(String name, String pwd, HttpServletRequest request){
if("zar".equalsIgnoreCase(name)&&"123".equalsIgnoreCase(pwd)){
//在session中存储用户信息,用于权限验证
request.getSession().setAttribute("users",name);
return "main";
} else{
request.setAttribute("msg","用户名或密码错误");
return "login";
}
}
}
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//是否登录过的判断
if (request.getSession().getAttribute("users")==null){
//没登录
request.setAttribute("msg","请先登录再访问");
request.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
return true;//放行请求
}
}
Original: https://www.cnblogs.com/LoginX/p/Login_X50.html
Author: 我没有bug
Title: SpringMVC笔记
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621632/
转载文章受原作者版权保护。转载请注明原作者出处!