2g SpringMVC基础.txt
UP 返回
1 简介
MVC M:Model V:View C:Controller - servlet/action/controller
Spring MVC是Spring提供的一个强大而灵活的web框架。借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单。这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其他bean,通过Spring的依赖注入功能,这些bean被注入到控制器中。
Spring MVC主要由DispatcherServlet、处理器映射【找控制器】、适配器【调用控制器的方法】、控制器【业务】、视图解析器、视图组成。
2.创建项目 █参见项目:D:\ProjectCodes\IDEA2017\springmvc-test1
2.1 导入springmvc jar包
创建工程同06
除了以前的jar,需要额外加入spring-webmvc的jar
2.2 在web.xml配置DispatcherServlet(WEB-INF目录下)
★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_3_1.xsd"
version="3.1">
<!--▶配置:所有的请求由SpringMVC管理-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<!--▶所有请求转发给DispatcherServlet-->
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
2.3 在WEB-INF目录下创建DispatcherServlet-servlet.xml(名字和位置默认是这个)
★DispatcherServlet-servlet.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!--▶1.配置url处理映射-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!--▶2.配置控制器处理适配器-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!--▶3.配置控制器-相当于配置了访问路径-->
<bean name="/user.do" class="com.dm.backoffice.web.controller.UserController"></bean>
<!--▶4.配置资源视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀和后缀,方便查找jsp(会自动加在controller中写的页面前后拼接)-->
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
2.4 配置DispatcherServlet-servlet.xml
参2.3中内容
2.5 创建个Controller控制器
public class UserController implements Controller { //▶注意导包时不要导错了,选org.springframework.web.servlet.mvc.Controller;
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mav=new ModelAndView("user/userlist"); //▶会和DispatcherServlet-servlet.xml中配置的前后缀相结合
mav.addObject("name","haha");
return mav;
}
}
2.6 创建一个userList.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户列表</title>
</head>
<body>
${name}:<br> ▶取出后台返回的name值
</body>
</html>
2.7运行项目,访问路径
浏览器输入:http://localhost:8080/user.do,运行
3.运行流程
首先浏览器发出请求,根据web.xml中的配置,该请求会交给DispatcherServlet处理
他再根据DispatcherServlet-servlet.xml的配置,将请求交给url处理映射BeanNameUrlHandlerMapping。该类会根据url的名字比对bean的name属性来寻找对应的controller,然后由SimpleControllerHandlerAdapter来执行对应的控制层,并返回页面模型modelandview
最后InternalResourceViewResolver会依据配置的前后缀查找jsp路径,响应页面
4.详解DispatcherServlet-servlet.xml属性
4.1 配置URL处理映射的方式有三种(▶了解即可,因为以后都是用注解来配)
BeanNameUrlHandlerMapping:通过url名字,找到对应的bean的name的控制器。如上述DispatcherServlet-servlet.xml中所示
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<bean name="/user.do" class="com.dm.backoffice.web.controller.UserController"></bean>
SimpleUrlHandlerMapping:通过key找到bean的id的控制器
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/user1.do">userController</prop> ▶这三个url都会指向下面的userController控制器
<prop key="/user2.do">userController</prop>
<prop key="/user3.do">userController</prop>
</props>
</property>
</bean>
<bean id="userController" class="com.dm.backoffice.web.controller.UserController"></bean>
ControllerClassNameHandlerMapping:不用配置访问路径,默认的访问路径就是类名(首字母变小写,后面加.do。具体的访问方式有区别,参视频,但是没必要去了解了)
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
<bean class="com.dm.backoffice.web.controller.UserController"></bean> ▶访问userController.do即可
4.2 配置控制器处理适配器:配置如何调用控制器的方法
SimpleControllerHandlerAdapter 执行controller,调用controller里面方法,返回modelAndView
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
▶该方式对应的控制层需要实现Controller,此方法返回一个ModelAndView,返回的页面可以直接设置好
HttpRequestHandlerAdapter 执行控制器,负责调用实现HttpRequestHandler接口的控制器
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
▶该方法对应的控制层需要实现HttpRequestHandler,此方法返回null,故需要自己写返回的页面路径:
public class HttpController implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("name","haha");
request.getRequestDispatcher("/WEB-INF/views/user/userlist.jsp").forward(request,response); //▶转发
}
}
4.3 命令控制器(演示的类过时了,spring4.2引用不了,代码无法跑起来,项目中没写代码。了解即可,相当于是底层实现)
■添加页面useradd.jsp
<form action="${pageContext.request.contextPath}/command.do" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
性别:<input type="text" name="gender"><br>
生日:<input type="text" name="birthday"><br>
<input type="submit">
</form>
■Command控制器
public class UserAddController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mav=new ModelAndView("user/useradd");
return mav;
}
}
public class CommandController extends AbstractCommandController{ //继承的这个父类找不到了
//▶指定哪个bean来接收参数
public CommandController(){
this.setCommandClass(User.class);
}
@Override
protected ModelAndView handle(HttpServletRequest requset,HttpServletResponse response,Object command,BindException errors) throws Exception{
//转成用户对象
User user =(User) command;
ModelAndView mv=new ModelAndView();
//添加数据
mv.addObject("user",user);
//返回页面
mv.setViewName("/user/info");
return mv;
}
}
■info.jsp
<body>
<!-- 从控制器中取数据 -->
${user.username} || ${user.password}
</body>
★DispatchServelt-sevlet配置文件
<bean name="/useradd.do" class="com.dm.backoffice.web.controller.UserAddController"></bean> ▶注意name中要加/
<bean name="/command.do" class="com.dm.backoffice.web.controller.CommandController"></bean>
★views结构
views\user下有两个页面,首先访问useradd.jsp,填好提交,进入command.do,再返回页面info.jsp
5.出现乱码问题解决方法
5.1 控制台tomcat输出中文乱码
点击tomcat设置页面,在VM options中输入-Dfile.encoding=UTF-8,下面两个下拉框都选Update classes and resources,确定,重启tomcat
5.2 POST请求乱码
<!-- 配置编码过滤器 -->
<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>
5.3 GET请求乱码
Tomcat8 默认进行了url编码,get请求不乱码,Tomcat7会乱码
在server.xml中配置
<Connector URIEncoding="UTF-8" connectionTimeout="2000" port="8080"........(省略)
6.注解配置
6.1 修改DispatchServelt-sevlet配置文件:
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!--注解配置控制器-->
<!--▶1.配置扫描包-->
<context:component-scan base-package="com.dm.backoffice.web.controller"/>
<!--▶2.配置处理映射-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--▶3.配置适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!--4.配置资源视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀和后缀,方便查找jsp-->
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
6.2 控制层代码
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/list")
public String list(){
return "user/userlist"; //▶访问/user/list.do即可进入该方法,并返回页面userlist(之所以需要.do是因为web.xml中配置了过滤器)。如果类上去除注解@RequestMapping("/user"),那就直接用方法上面的url来访问即可
}
}
7.表单接收页面数据的方式
7.1 方法一:直接在方法参数中写,会自动转过来
■register.jsp(通过/user/toRegister.do访问)
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/user/register.do" method="post"> ▶设置提交路径
用户名:<input type="text" name="username"><br>
密码:<input type="text" name="password"><br>
性别:<input type="text" name="gender"><br>
年龄:<input type="text" name="age"><br>
生日:<input type="text" name="birthday"><br>
爱好:<input type="checkbox" name="hobbyIds" value="1">打球
<input type="checkbox" name="hobbyIds" value="2">打人
<input type="checkbox" name="hobbyIds" value="3">打假<br>
<input type="submit">
</form>
</body>
</html>
■Controller
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/list")
public String list(){
return "user/userlist";
}
@RequestMapping("/toRegister") //▶进入注册页面
public String toRegister(){
return "user/register";
}
@RequestMapping("/register")
public String register(String username, String password, int age, String gender, Date birthday,String[] hobbyIds){ //▶直接把页面上的变量写进参数
System.out.println(username);
System.out.println(password);
System.out.println(age);
System.out.println(gender);
System.out.println(birthday); //▶date的参数在页面上必须采用标准的XX/XX/XX(三个里面必须有年月日)格式,否则转不了
System.out.println(Arrays.toString(hobbyIds));
return "user/info";
}
}
7.2 方法二:将变量封装进pojo(User)
■Controller中方法
@RequestMapping("/register2")
public String register(User user){
System.out.println(user);
return "user/info";
}
7.3 方法三:接收包装类型参数(用一个UserExt类,其中含有一个成员User。相当于一个包装类)
■Controller中方法
@RequestMapping("/register3")
public String register3(UserExt userExt){
System.out.println(userExt);
return "user/info";
}
■相应jsp中变量的name也需要改为user.XXX的格式
用户名:<input type="text" name="user.username"><br>
密码:<input type="text" name="user.password"><br>
性别:<input type="text" name="user.gender"><br>
7.4 如何接收集合(List和Map)
■包装类中放入一个链表
public class UserExt {
private User user;
private List<User> users=new ArrayList<>();
private Map<String,Object> infos=new HashMap<>(); //(get set toString都省略)
}
■Controller方法
@RequestMapping("/register4")
public String register4(UserExt userExt){
System.out.println(userExt.getUsers());
System.out.println(userExt.getInfos());
return "user/info";
}
■register.jsp(jsp中集合名要和UserExt保持一致,/user/toRegister.do访问)
<body>
接收集合类型参数<br>
<form action="${pageContext.request.contextPath}/user/register4.do" method="post">
用户名1:<input type="text" name="users[0].username"><br> ▶链表中元素写法
密码1:<input type="text" name="users[0].password"><br>
<hr>
用户名2:<input type="text" name="users[1].username"><br>
密码2:<input type="text" name="users[1].password"><br>
<input type="submit" value="保存">
</form>
<br>
接收Map类型参数<br>
<form action="${pageContext.request.contextPath}/user/register5.do" method="post">
用户名1:<input type="text" name="infos['username']"><br> ▶Map中元素写法
密码1:<input type="text" name="infos['password']"><br>
<input type="submit">
</form>
</body>
8.SpringMVC和Struts的区别
8.1 实现机制:Struts2是基于过滤器实现的。Springmvc基于servlet实现。
运行速度:Servlet比过滤器快。
8.2 Struts2是多例,每一次请求,都会创建一个Action对象。请求来了以后,struts2创建多少个对象:ActionContext,valuestack,UAction,ActionSuport,ModelDriven
Springmvc是单例。同一个Controller请求,只会创建一个Controller
8.3 参数封装来分析:Struts基于属性进行封装,Action有参数属性。
Springmvc基于方法封装,参数是写在Controller的方法。
9.其他说明
9.1 model传递数据
jsp:<a href="${pageContext.request.contextPath}/user/edit.do?id=${user.id}">修改</a>
controller:
@RequestMapping("/edit")
public String edit(int id ,Model model){
User user=new User("seds",17,"dfdf",new Date()); //模拟
user.setId(id);
model.addAttribute("user",user);
return "user/useredit";
}
9.2 url模版映射:可以restfull软件架构
jsp采用另外一种连接写法:<a href="${pageContext.request.contextPath}/user/edit1/${user.id}/${user.username}.do">修改</a> ▶将参数拼接在url中
controller:
@RequestMapping("/edit1/{id}/{username}")
public String edit1(@PathVariable int id ,@PathVariable String username, Model model){ ▶@PathVariable可直接拿到参数
User user=new User("seds",17,"dfdf",new Date());
user.setId(1);
model.addAttribute("user",user);
return "user/useredit";
}
web.xml需要在配置一套url过滤:
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/rest/*</url-pattern> ▶访问http://localhost:8080/rest/user/edit1/1/1和上面http://localhost:8080/user/edit1/1/1.do效果是一样的
</servlet-mapping>
9.3 转发与重定向(转发地址不变,重定向改变)
@RequestMapping("test1")
public String test1(){
return "forward:list.do"; //同一个控制器的转发(会转到list.do的控制器)
}
@RequestMapping("/test1")
public String test1(){
return "forward:/user/list.do"; //不同控制器的转发(会转到/user/list.do的控制器)
return "redirect:/user/list.do"; //重定向(同一个控制器的重定向就不演示了,类似的)
}
9.4 RequestParam参数
/**
* RequestParam参数描述
* value:参数名称
* defaultValue:默认值
* required:参数是否必须有值,如果为true,参数又为空,会报错(存在默认值时该属性就没用了)
* */
@RequestMapping("/test2")
public String test2(@RequestParam(value="uid",required=true,defaultValue = "20") Integer uid){
System.out.println(uid); //http://localhost:8080/user/test2.do?uid=100打印100;http://localhost:8080/user/test2.do打印20
return "forward:list.do";
}
9.5 想使用标签<c:forEach items="${userList}" var="user">,需要jsp页面添加<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>,
引入jar支持:F:\BaiduNetdiskDownload\2019年4月黑马程序员教程\01-黑马IDEA版本Java基础+就业课程\4.框架\Java开发工具\jar包\jstl-X.X.jar
DOWN 返回