Java开源框架,Spring Framework的一个独立模块。
MVC框架,在项目中开辟MVC层次架构
对控制器中的功能包装简化扩展践行工厂模式,功能架构在工厂之上。
名称 | 职责 |
---|---|
Model | 模型:承载数据,并对用户提交请求进行计算的模块。分为两类,一类称为数据承载Bean,一类称为业务处理Bean。所谓数据承载Bean是值实体类,专门承载业务数据的,如Student、User等。而业务处理Bean则是指Service或Dao对象,专门用于处理用户提交请求的 |
View | 视图:渲染数据,生成页面。对应项目中的Jsp , html 等 作用是与用户交互 展示数据 |
Controller | 控制器:用于将用户请求转发给相应的Model进行处理,并处理Model的计算结果向用户提供相应响应 |
用户通过View页面向服务端发送请求,可以是表单请求、超链接请求、AJAX请求等。
服务端Controller控制器接收到请求后对请求进行解析,找到相应的Model对用户请求进行处理。
Model处理后,将处理结果再交给Controller。
Controller接到处理结果后,根据处理结果找到要作为向客户端发回的响应View页面。页面经渲染后,再发给客户端。
MVC是现下软件开发中的最流行的代码结构形态;
人们根据负责的不同逻辑,将项目中的代码分成 M V C 3个层次;
层次内部职责单一,层次之间耦合度低;
符合低耦合 高内聚的设计理念。也实际有利于项目的长期维护。
org.springframework
spring-webmvc
5.2.0.RELEASE
作为MVC框架,首先要解决的是:如何能够收到请求!
所以MVC框架大都会设计一款前端控制器,选型在 Servlet 或 Filter两者之一,在框架最前沿率先工作,接收所有请求。
此控制器在接收到请求后,还会负责springMVC的核心的调度管理,所以既是前端又是核心。
- 补充:DispatcherServlet前端控制器,是框架提供的,作用统一处理请求和响应,整个流程的控制中心,是由它来调用其他组件处理用户的请求。
web.xml文件配置:
mvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc.xml
1
mvc
/
encoding
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
encoding
/*
等价于之前定义的Servlet。
@Controller // 交由spring创建bean对象
@RequestMapping("/hello") // 访问路径
public class HelloController {
@RequestMapping("/hello1")
public String hello(){
return "index"; // 跳转到index.jsp
}
@RequestMapping("/hello2")
public String hello2(){
return "pages/main"; // 跳转到pages包下的main.jsp
}
}
URL地址栏输入:
- http://localhost:8080/hello/hello1
- http://localhost:8080/hello/hello2
请求参数和方法的形参同名即可。
- springMVC默认可以识别的日期字符串格式为: YYYY/MM/dd HH:mm:ss
- 通过@DateTimeFormat可以修改默认日志格式
@RequestMapping("/test1")
public String test1Param(Integer id, String name, Boolean gender,@DateTimeFormat(pattern = "yyyy-MM-dd") Date birthday){
// springmvc自动接收参数,并且转换参数类型
System.out.println(id);
System.out.println(name);
System.out.println(gender);
System.out.println(birthday);
return "index";
}
浏览器访问: http://localhost:8080/.../test1?id=001&name=张三&gender=true&birthday=2002-12-11
请求参数和实体类的属性需要同名。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String name;
private Boolean gender;
/**
* 设置日期格式
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
}
@RequestMapping("/test2")
public String test2Param(User user){
System.out.println(user);
return "index";
}
浏览器访问:http://localhost:8080/.../test2?id=001&name=张三&gender=true&birthday=2000-11-22
简单类型数组
@RequestMapping("/test3")
public String test3Param(String[] hobby){
for (String s : hobby) {
System.out.println(s);
}
return "index";
}
浏览器访问:http://localhost:8080/.../test3?hobby=football&hobby=basketball
@Data
public class UserList {
private List users;
}
@RequestMapping("/test4")
public String testParam4(UserList userList){
for(User user:userList.getUsers()){
System.out.println(user);
}
return "index";
}
浏览器访问:
post请求:http://.../test4?userList[0].id=111&users[0].name=tom&users[0].gender=false&users[0].birthday=2000-04-02&users[1].id=2&....
@RequestMapping("/hello/{id}")
// @PathVariable将{id}路径匹配到值赋给id参数
// 路径名和参数名相同则@PathVariable("id")可简写为 @PathVariable
public String testParam5(@PathVariable("id") Integer id){
System.out.println("id:"+id);
return "index";
}
// http://localhost:8989/.../hello/10 {id}匹配到10
注意:@PathVariable将{id}路径匹配到值赋给id参数
路径名和参数名相同则@PathVariable("id")可简写为 @PathVariable
@RequestMapping("/hello/{username}")
public String testParam6(@PathVariable("username") String name){//将{username}路径匹配到的值赋给name参数
System.out.println("username:"+name);
return "index";
}
// http://localhost:8989/.../hello/tom {username}匹配到tom
1.页面中字符集统一
- JSP : <%@page pageEncoding="utf-8" %>
- HTML :
2.tomcat中字符集设置,对get请求中,中文参数乱码有效
3.在web.xml中设置此filter,对post请求中,中文参数乱码有效
encoding
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
encoding
/*
@Controller
@RequestMapping("/forw")
public class ForwardController {
@RequestMapping("/test1")
public String test1(HttpServletRequest request){
System.out.println("test forward1");
// 这也是转发,是走视图解析器的转发
// return "index";
//请求转发传值通过request.setAttribute
request.setAttribute("name","zs");
// 这种是不走视图解析器的转发
return "forward:/page/success.jsp";
}
@RequestMapping("/test2")
public String testForward2(){
System.out.println("test forward2");
// 转发到 /forw/test1
return "forward:test1"; // 这种是相对路径(转发到本类中的test1)
// 转发到 /forw/test1
// return "forward:/forw/test1"; // 这种是绝对路径
}
}
- test1中model.addAttribute("name",name),在jsp中取值方式:${name}
- 注意:转发也可以不走视图解析器,如:forward:/page/success.jsp
@Controller
@RequestMapping("/redir")
public class RedirectController {
@RequestMapping("/test1")
public String test1(HttpSession session){
System.out.println("test redirect1");
// 重定向传值通过session.setAttribute
session.setAttribute("name","ls");
// 这种是不走视图解析器的转发
return "redirect:/page/success.jsp";
}
@RequestMapping("/test2")
public String testForward2(){
System.out.println("test redirect2");
// 重定向到 /redir/test1
return "redirect:test1"; // 这种是相对路径(转发到本类中的test1)
// 重定向到 /redir/test1
// return "redirect:/redir/test1"; // 这种是绝对路径
}
}
- 在增删改之后,为了防止请求重复提交,重定向跳转
- 在查询之后,可以做转发跳转
C得到数据后,跳转到V,并向V传递数据。进而V中可以渲染数据,让用户看到含有数据的页面。
- 转发跳转: Request作用域
- 重定向跳转:Session作用域
转发传给页面值
@RequestMapping("/test1")
public String testServlet(HttpServletRequest request, User user){
user.setName("张三");
request.setAttribute("user",user);
System.out.println("scope test1");
return "forward:/page/success.jsp";
//jsp中取值方式${user.name}
}
重定向传给页面值
@RequestMapping("test2")
public String testServlet2(HttpSession session,User user){
user.setName("李四");
session.setAttribute("user",user);
System.out.println("scope test1");
return "forward:/page/success.jsp";
//jsp中取值方式${user.name}
}
//jsp中用EL表达式 取值即可
${user.birth}
${age}
//model中的数据等价于放在了request中,会在V渲染之前,将数据复制一份给request
@RequestMapping("/test3")
public String testData(Model model){
// model中的数据等价于放在了request汇总
model.addAttribute("name", "王二1");
//转发带.jsp不走视图解析器
return "forward:/page/success.jsp";
//jsp中取值方式${name}
}
//modelandview 封装了model和view
@RequestMapping("/test4")
public ModelAndView testData(){//返回值类型为ModelAndView
//新建ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
// 使用model存储数据
modelAndView.addObject("age",18);
// 设置视图名,即如何跳转
modelAndView.setViewName("page/success"); //等价 return "page/success";
return modelAndView;
//jsp中取值方式${age}
}
@SessionAttributes({"gender","name"}) :model中的 name和gender 会存入session中
SessionStatus 移除session
@Controller
@SessionAttributes({"gender","name"}) // model中的 name和gender 会存入session中
public class UserController {
@RequestMapping("/hello")
public String hello(Model m){
m.addAttribute("gender",true); // 会存入session
mv.addObject("name","zhj"); // 会存入session
return "index";
}
@RequestMapping("/hello2")
public String hello(SessionStatus status){
// 移除通过SessionAttributes存入的session
status.setComplete();
return "index";
}
}
使用Map和ModelMap也可以在页面中也可以通过${user}取值。
@RequestMapping("/test5")
public String test5(Map map){
User user = new User();
user.setName("阿伟");
user.setBirthday(new Date());
map.put("user", user);
return "page/success";
}
@RequestMapping("/test6")
public String test6(ModelMap map){
User user = new User();
user.setName("阿伟");
user.setBirthday(new Date());
map.put("user", user);
return "page/success";
}
静态资源:html,js文件,css文件,图片文件
静态文件没有url-pattern,所以默认是访问不到的,之所以可以访问,是因为,tomcat中有一个全局的servlet:org.apache.catalina.servlets.DefaultServlet,它的url-pattern是 "/",是全局默认的Servlet.。所以每个项目中不能匹配的静态资源的请求,有这个Servlet来处理即可。
在SpringMVC中DispatcherServlet也采用了 “/” 作为url-pattern, 则项目中不会再使用全局的Serlvet,则静态资源不能完成访问。
如果DispathcerServlet采用其他的url-pattern,web.xml中所有访问handler的路径都要以action结尾!!
mvc9