Spring MVC

Spring MVC

1.什么是SpringMVC?

​ SpringMVC(Modle View Controller)是一个用来简化web开发的mvc框架,springMVC是spring框架的一部分,它是一种软件架构思想,其核心是一个软件划分为三种不同类型的模块,分别是模型,视图和控制器,其中模型用来封装业务逻辑视图用来处理表示逻辑,控制器(处理器)用来协调模型和视图,一般用java类充当模型,使用servlet充当控制器,jsp充当视图。

使用MVC框架思想实现一个简单的计算BMI指数

在这里插入图片描述

1.1BMI前端html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>计算BMI指数</title>
</head>
<body>
	<div>
		<form action="bmiservlet" method="get">
			<h3>计算BMI指数</h3><br>
			身高(m):<input type="text" name="height"/><br>
			体重(kg):<input type="text" name="weight"/><br>
			<input type="submit" value="确定">
		</form>
	</div>
</body>
</html>
1.2web.xml配置文件
  <servlet>
  	<servlet-name>bmi</servlet-name>
  	<servlet-class>web.BMIContorl</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>bmi</servlet-name>
  	<url-pattern>/bmiservlet</url-pattern>
  </servlet-mapping>
1.3控制层(控制器)
package web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import service.UserService;
import service.UserServiceImpl;

public class BMIContorl extends HttpServlet{
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		String height=req.getParameter("height");
		String weight=req.getParameter("weight");
		//调用业务层并返回结果
		UserService us=new UserServiceImpl();
		String state=us.userBmiservlet(height, weight);
		//数据绑定
		req.setAttribute("state",state);
		//转发
		req.getRequestDispatcher("WEB-INF/View.jsp").forward(req, res);
	}
}

注意:WEB-INF下的页面只能由后端才能调用,前端无法直接获取。

1.4业务层(模型)
package service;
/*
 * 业务层
 */
public interface UserService {
	String userBmiservlet(String height,String weight);
}
package service;
/*
 * 业务层
 */
public class UserServiceImpl implements UserService{

	@Override
	public String userBmiservlet(String height, String weight) {
		//计算bmi指数
		double bmi=Double.parseDouble(weight)/Math.pow(Double.parseDouble(height),2);
		String state="刚刚好";
		if(bmi>24){
			state="过重";
		}
		if(bmi<22){
			state="过轻";
		}
		return state;
	}
}

1.5前端JSP页面(视图 )
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
	你的BMI指数是:${state}
</body>
</html>
1.6执行结果

在这里插入图片描述

2. SpringMVC的五大组件

​ DispatcherServlet(前端控制器)
​ HandleMapping(请求地址)
​ Controller(处理器/控制器)
​ ModelAndView(处理结果和视图名·)
​ ViewResolver(视图解析器)

SpringMVC工作原理图

在这里插入图片描述

2.1web.xml配置文件
<servlet>
  		<servlet-name>springMvc</servlet-name>
  		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  		<!--
  		DispatcherServlet在初始化时,会启动spring容器,所以知道Spring配置文件的位置,可以
  		通过contextConfigLocation初始化参数来指定位置
  		-->
  		<init-param>
  				<param-name>contextConfigLocation</param-name>
  				<param-value>classpath:spring-mvc.xml</param-value>
  		</init-param>
  </servlet>
  <servlet-mapping>
  		<servlet-name>springMvc</servlet-name>
  		<url-pattern>*.do</url-pattern>
  </servlet-mapping>
2.2Spring-mvc.xml配置文件
	 <!--配置HandleMapping,目的告诉DispatherServlet的请求路径和Controller的对应关系-->
	 <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
	 		<property name="mappings">
	 			<props>
	 				<!--key="hello.do"请求地址;helloController对应Controller被Spring管理后的id值-->
	 				<prop key="hello.do">helloController</prop>
	 			</props>
	 		</property>
	 </bean>
	 
	 <!--配置控制层/控制器-->
	 <bean id="helloController" class="web.HelloWorld"/>
	 
	 <!--配置视图解析器(ViewResolver),目的是告诉DispatherServlet视图名对应的视图对象,例如某个jsp-->
	 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	 		<!--prefix:前缀,根据绝对路径下去找相关的视图-->
	 		<!--suffix:后缀:根据前缀和视图名去找相关的视图文件-->
	 		<property name="prefix" value="/WEB-INF/"/>
	 		<property name="suffix" value=".jsp"/>
	 </bean>

注意:
在这里插入图片描述

2.3控制层(Controller(处理器/控制器))
package web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

/*
 * 控制层需要实现Controller接口
 */
public class HelloWorld implements Controller{

	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		ModelAndView mav=new ModelAndView("View");
		//数据绑定
		request.setAttribute("result","超超最帅");
		return mav;
	}
	
}

返回视图名和结果:mav和result;

2.4JSP前端页面
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
	 hello!树先生!
	${result}
</body>
</html>
2.5执行结果

在地址栏输入hello.do:
在这里插入图片描述

得到View.jsp页面。

2.6总结

​ 当我们在地址栏输入hello.do时,DispatcherServlet(前端控制器)会依据HandleMapping知道请求路径和Controller的对应关系;然后DispatcherServlet(前端控制器)再去通知Controller让其返回ModelAndView视图名和结果;然后DispatcherServlet(前端控制器)再将这个视图名和结果交给ViewResolver(视图解析器),让其去拼接成一个完整的jsp页面地址;最后DispatcherServlet(前端控制器)再拿着这个地址找到对应的jsp页面,通过转发将其转发出去。

​ 形象点来说:SpringMVC工作原理就像是一个Boss和四个职工之间的关系,四个职工有着不同的工作任务,而Boss只负责分发任务和验收成果,具体的工作过程他是不管不问的。

3.MVC注解驱动的方式

3.1web.xml配置文件

几乎不用动什么,只需把一中的classpath:spring-mvc.xml改为

classpath:spring-mvc2.xml,因为我们会创建一个新的容器。

3.2Spring-mvc2.xml

注意:配置视图解析器是省略不了的

	<!--配置组件扫描-->
	<context:component-scan base-package="web"/>
	
	<!--配置MVC注解驱动-->
	<mvc:annotation-driven/>
	
	 
<!--配置视图解析器(ViewResolver),目的是告诉DispatherServlet视图名对应的视图对象,例如某个jsp-->
	 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	 		<property name="prefix" value="/WEB-INF/"/>
	 		<property name="suffix" value=".jsp"/>
	 </bean>
3.3控制层

@Controller:用于标记这是一个控制层,Spring容器会扫描到它

@RequestMapping:用于处理地址与对象之间的依赖关系,相当于HandleMapping

package web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

/*
 * 控制层也就是控制器/处理器
 */
@Controller
@RequestMapping("user")
public class HelloWorld2{

	@RequestMapping("hello.do")
	public ModelAndView hello(){
		return new ModelAndView("View");
	}
	
	@RequestMapping("hello2.do")
	public String hello2(){
		return "hello";
	}
}
3.4执行结果

当我们在地址栏输入user/hello.do时会返回View.jsp页面

当我们在地址栏输入user/hello2.do时会返回hello.jsp页面

4.控制层处理多个参数的方式

4.1前端html页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
	<div align="center">
		<h2>登录</h2>
		<form action="user/login10.do" method="get">
			用户名:<input type="text" name="username"/>
			密码:<input type="password" name="userpwd"/>
			<input type="submit" value="登录">
		</form>		
	</div>
</body>
</html>

注意:

在这里插入图片描述

当我们访问不同地址时只需改变此值即可

4.2方式一

DispatherServlet默认以转发形式到页面

	@RequestMapping("login.do")
	public String login(){
		return "login";
	}
4.3方式二

DispatherServlet利用java反射分析方法的结构,会将对应的请求参数赋值给响应的形参.如果请求参数和形参不一致则需要使用@RequestParam(请求参数名)接收请求参数来处理,如:public String userLogin(@RequestParam(“username”)String usernames,String userpwd)

	@RequestMapping("login2.do")
	public String userLogin(String username,String userpwd){
		System.out.println(username+","+userpwd);
		return "login";
	}
4.4方式三

DispatcherServlet在调用Controller的方法前,会利用java发射机制分析方法的结构,如果发现有一个request对象,则DispatcherServlet会将request作为一个参数传递进来。

	@RequestMapping("login3.do")
	public String Login2(HttpServletRequest request){
		String username=request.getParameter("username");
		System.out.println(username);
		return "login";
	}
4.5方式四

适用封装成对象的方法接收请求参数,请求参数需要和bean对象中的bean属性保持一致。

将参数封装到user对象中,需要我们创建User类

package entry;

import java.io.Serializable;

public class User implements Serializable{

	private static final long serialVersionUID = 1L;
	String username;
	String userpwd;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		System.out.println("测试1");
		this.username = username;
	}
	public String getUserpwd() {
		return userpwd;
	}
	public void setUserpwd(String userpwd) {
		System.out.println("测试2");
		this.userpwd = userpwd;
	}
	@Override
	public String toString() {
		return "User [username=" + username + ", userpwd=" + userpwd + "]";
	}
}
	@RequestMapping("login4.do")
	public String Login4(User user){
		System.out.println(user.getUsername()+","+user.getUserpwd());
		return "login";
	}
4.6方式五

将绑定的数据转发到jsp页面

	@RequestMapping("login5.do")
	public String Login5(User user,HttpServletRequest request){
		request.setAttribute("name",user.getUsername());
		return "login";
	}
4.7方式六

如果返回值是ModelAndView对象,则需要使用map集合添加相关的数据, 最后将map集合转到modelAndview对象中;DispatcherServlet会将key作为绑定名,将数据绑定到request对象上。

	@RequestMapping("login6.do")
	public ModelAndView Login6(User user){
		String name=user.getUsername();
		Map<String,Object> map=new HashMap<String, Object>();
		map.put("name",name);
		ModelAndView mav=new ModelAndView("login",map);
		return mav;
	}
4.8方式七

session绑定

	@RequestMapping("login7.do")
	public String Login7(User user,HttpSession session){
		session.setAttribute("name",user.getUsername());
		return "login";
	}
4.9方式八

DispatcherServlet以addAttribute的绑定名(name)作为绑定名, 将数据绑定到request对象上

	@RequestMapping("login8.do")
	public String Login8(User user,ModelMap model){
		model.addAttribute("name",user.getUsername());
		return "login";
	}
4.10方式九

重定向方式一

	@RequestMapping("login9.do")
	public String Login9(User user){
		return "redirect:index.do";
	}
	
	@RequestMapping("index.do")
	public String index(){
		return "index";
	}

执行index.jsp页面

4.11方式十

重定向方式二

	@RequestMapping("login10.do")
	public ModelAndView Login10(){
		//创建重定向对象RedirectView(重定向的地址)
		RedirectView rd=new RedirectView("index.do");
		ModelAndView mav=new ModelAndView(rd);
		return mav;
	}

	@RequestMapping("index.do")
	public String index(){
		return "index";
	}

与重定向方式一结果相同

4.12总结

大多数处理参数的方式都是绑定和转发,有些虽然表面没用,底层还是用的request绑定和转发的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值