创建web工程
使用mven创建
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zym</groupId> <artifactId>spring_mvc_test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>spring_mvc_test Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!--日志--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.4</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency> <!--J2EE--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--mysql驱动包--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> </dependencies> <build> <finalName>spring_mvc_test</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>
目录结构
springconfig.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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--配置controller扫描包--> <context:component-scan base-package="com.zym.controller"/> </beans>
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"> <display-name>Archetype Created Web Application</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!--配置SpringMVC前端控制器--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springconfig.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
Springmvc架构
框架结构
架构流程
1、用户发送请求至前端控制器DispatcherServlet
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
5、执行处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9、ViewReslover解析后返回具体View
10、 DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
11、 DispatcherServlet响应用户
组件说明
以下组件通常使用框架提供实现:
u DispatcherServlet:前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
u HandlerMapping:处理器映射器
HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
u Handler:处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。
u HandlAdapter:处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
下图是许多不同的适配器,最终都可以使用usb接口连接
u ViewResolver:视图解析器
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。
u View:视图
springmvc框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面。
说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。 需要用户开发的组件有handler、view |
默认加载的组件
组件扫描器
使用组件扫描器省去在spring容器配置每个Controller类的繁琐。
使用<context:component-scan>自动扫描标记@Controller的控制器类,
在springmvc.xml配置文件中配置如下:
<!-- 配置controller扫描包,多个包之间用,分隔 -->
<context:component-scan base-package="com.jy.controller" />
注解映射器和适配器
配置处理器映射器
注解式处理器映射器,对类中标记了@ResquestMapping的方法进行映射。根据@ResquestMapping定义的urI匹配@ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器。
HandlerMethod对象中封装url对应的方法Method。
从spring3.1版本开始,废除了DefaultAnnotationHandlerMapping的使用,推荐使用RequestMappingHandlerMapping完成注解式处理器映射。
在springmvc.xml配置文件中配置如下:
<!-- 配置处理器映射器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
注解驱动
直接配置处理器映射器和处理器适配器比较麻烦,可以使用注解驱动来加载。
SpringMVC使用<mvc:annotation-driven>自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter
可以在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解处理器和适配器的配置。
<!-- 注解驱动 -->
<mvc:annotation-driven />
视图解析器
视图解析器使用SpringMVC框架默认的InternalResourceViewResolver,这个视图解析器支持JSP视图解析 在springmvc.xml配置文件中配置如下: <!-- Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" --> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 配置逻辑视图的前缀 --> <property name="prefix" value="/WEB-INF/jsp/" /> <!-- 配置逻辑视图的后缀 --> <property name="suffix" value=".jsp" /> </bean> 逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为ItemList,则最终返回的jsp视图地址: “WEB-INF/jsp/itemList.jsp”
最终jsp物理地址:前缀+逻辑视图名+后缀
整合mybatis
一堆配置文件
增删改查
查询操作
@Controller public class ItemController { @Autowired private ItemInf itemInf; // private List<Product> products; @RequestMapping("/list") public ModelAndView selectItemList(){ List<Product> products = itemInf.SelectAll();//调用service中的SelectAll方法 System.out.println("==============="); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("list",products); modelAndView.setViewName("list"); //设置返回的视图 return modelAndView;
改
//查询要修改的商品 @RequestMapping("/showItems") // public ModelAndView showItems(HttpServletRequest req){ // public String showItems(HttpServletRequest req,Model model){ //这里可以使用model来进行操作,返回String // public String showItems(HttpServletRequest req,ModelMap model){ //这里可以使用ModelMap进行操作,返回String,ModelMap是model的子类,有更多的功能 public String showItems(@RequestParam(value="itemId",required=true,defaultValue="1")Integer id,ModelMap model){//黄色的建议使用封装类型,他可以接收空值,可以进行判断操作 // String id = req.getParameter("id"); // Items item =itemService.selectItemsById(Integer.parseInt(id)); Items item =null; if(id!=null){ item =itemService.selectItemsById(id); }else{ System.out.println("没有传id值!"); } // ModelAndView mv = new ModelAndView(); // mv.addObject("item", item); // mv.setViewName("update"); // return mv; //model model.addAttribute("item", item); return "update"; } //修改商品 @RequestMapping("/updateItems") public ModelAndView updateItems(Items item){ ModelAndView mv = new ModelAndView(); int flag=itemService.updateItems(item); if(flag>0){ mv.setViewName("redirect:itemslist");//重定向到一个uri// }else{ mv.addObject("msg", "修改失败!"); mv.setViewName("error"); } return mv;
参数绑定
默认支持的参数类型
HttpServletRequest
HttpServletResponse
HttpSession
绑定简单类型
当请求的参数名称和处理器形参名称一致时会将请求参数与形参进行绑定。
这样,从Request取参数的方法就可以进一步简化。
@RequestMapping("/itemEdit") public String queryItemById(int id, ModelMap model) { return "itemEdit"; }
支持的数据类型
参数类型推荐使用包装数据类型,因为基础数据类型不可以为null 整形:Integer、int 字符串:String 单精度:Float、float 双精度:Double、double 布尔型:Boolean、boolean 说明:对于布尔类型的参数,请求的参数值为true或false。或者1或0 请求url: http://localhost:8080/xxx.action?id=2&status=false 处理器方法: public String editItem(Model model,Integer id,Boolean status)
@RequestParam
使用@RequestParam常用于处理简单类型的绑定。 value:参数名字,即入参的请求参数名字,如value=“itemId”表示请求的参数 区中的名字为itemId的参数的值将传入 required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报错 TTP Status 400 - Required Integer parameter 'XXXX' is not present defaultValue:默认值,表示如果请求中没有同名参数时的默认值
<a href="showItems?itemId=${item.id}">修改</a> </td>
public String showItems(@RequestParam(value="itemId",required=true,defaultValue="1")Integer id,ModelMap model){
\\黄色部分需要对应,defaultValue是默认值
}
解决post乱码问题
在web.xml中添加如下代码
<filter> <filter-name>encoding</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!-- 设置编码参是UTF8 --> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
对于get请求中文参数出现乱码解决方法有两个
修改tomcat配置文件添加编码与工程编码一致,如下: <Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/> 另外一种方法对参数进行重新编码: String userName =new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8") ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
自定义参数绑定
由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。
前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。可以在springmvc处理器适配器上自定义转换器Converter进行参数绑定。
一般使用<mvc:annotation-driven/>注解驱动加载处理器适配器,可以在此标签上进行配置。
自定义Converter
//Converter<S, T> //S:source,需要转换的源的类型 //T:target,需要转换的目标类型 public class DateConverter implements Converter<String, Date> { @Override public Date convert(String source) { try { // 把字符串转换为日期类型 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss"); Date date = simpleDateFormat.parse(source); return date; } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 如果转换异常则返回空 return null; } }
配置Converter
<!-- 配置注解驱动 --> <!-- 如果配置此标签,可以不用配置... --> <mvc:annotation-driven conversion-service="conversionService" /> <!-- 转换器配置 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class=" com.jy.util.DateConverter" /> </set> </property> </bean>
分页操作
在mybatis的配置文件中
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="autoMappingBehavior" value="FULL" /> </settings> <!-- 配置pojo类别名 --> <typeAliases> <package name="com.jy.pojo"/> </typeAliases> <!-- 分页插件 --> <plugins> <plugin interceptor="com.github.pagehelper.PageHelper"> <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库--> <property name="dialect" value="mysql" /> <!-- 该参数默认为false 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 和startPage中的pageNum效果一样 --> <property name="offsetAsPageNum" value="true" /> <!-- 该参数默认为false 设置为true时,使用RowBounds分页会进行count查询 --> <property name="rowBoundsWithCount" value="true" /> <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 (相当于没有执行分页查询,但是返回结果仍然是Page类型) --> <property name="pageSizeZero" value="true" /> <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 --> <property name="reasonable" value="true" /> <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 --> <property name="params" value="pageNum=start;pageSize=limit;pageSizeZero=zero;reasonable=heli;count=contsql" /> </plugin> </plugins> </configuration>
controller层
//查询图书列表 @RequestMapping("/booklist") //第一次访问显示第一页数据 public ModelAndView selectBookList(@RequestParam(defaultValue="1")Integer pageNum,@RequestParam(defaultValue="3")Integer pageSize){ ModelAndView mv = new ModelAndView(); //开启分页 PageHelper.startPage(pageNum, pageSize);//pageNum :当前是第几页;pageSize:每页最多显示记录数 //查询所有记录 List<Book> list = service.selectBookList(); //分页 PageInfo<Book> pi=new PageInfo<>(list); mv.addObject("pi", pi); mv.setViewName("list"); return mv;