SpringMVC思路
步骤:
1、创建项目
2、导入jar包
3、Web.xml :dispatcherservlet
4、Springmvc-servlet.xml
是<servlet-name>springmvc</servlet-name>的映射文件,有时会加位置contextConfigLocation。
<prop key="/index">indexController</prop>表示访问路径url:/index会交给id=IndexContrller的bean处理,<bean id="indexController" class="controller.IndexController"></bean>
5、IndexController.java
控制类 IndexController实现接口Controller ,提供方法handleRequest处理请求,
SpringMVC通过 ModelAndView 对象把模型和视图结合在一起,表示视图index.jsp。
模型数据是 message,内容是 “Hello Spring MVC”。
public class IndexController implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)throws Exception { ModelAndView mav = new ModelAndView("index.jsp"); mav.addObject("message", "Hello Spring MVC"); return mav; } } |
6、Index.jsp
在WebContent目录下创建index.jsp,通过EL表达式显示message的内容,
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%> <h1>${message}</h1> |
7、部署tomcat,访问路径:http://127.0.0.1:8080/springmvc/index
8、效果图
原理图
1. 用户访问 /index
2. 根据web.xml中的配置 所有的访问都会经过DispatcherServlet
3. 根据 根据配置文件springmvc-servlet.xml ,访问路径/index
会进入IndexController类
4. 在IndexController中指定跳转到页面index.jsp,并传递message数据
5. 在index.jsp中显示message信息
往ModelAndView对象mav中存入模型数据Message,跳转到index.jsp页面。
执行流程
1. 用户发起请求到前端控制器(Controller)
2. 前端控制器没有处理业务逻辑的能力,需要找到具体的模型对象处理(Handler),到处理器映射器(HandlerMapping)中查找Handler对象(Model)。
3. HandlerMapping返回执行链,包含了2部分内容: ① Handler对象、② 拦截器数组
4. 前端处理器通过处理器适配器包装后执行Handler对象。
5. 处理业务逻辑。
6. Handler处理完业务逻辑,返回ModelAndView对象,其中view是视图名称,不是真正的视图对象。
7. 将ModelAndView返回给前端控制器。
8. 视图解析器(ViewResolver)返回真正的视图对象(View)。
9. (此时前端控制器中既有视图又有Model对象数据)前端控制器根据模型数据和视图对象,进行视图渲染。
10. 返回渲染后的视图(html/json/xml)返回。
11. 给用户产生响应。
补充
视图定位
定义jsp文件的位置,视图解析器
修改springmvc-servlet.xml,增加
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/page/" />
<property name="suffix" value=".jsp" />
</bean>
其作用是把视图约定在 /WEB-INF/page/*.jsp 这个位置
把IndexController类的这一行代码
ModelAndView mav = new ModelAndView("index.jsp");
改为
ModelAndView mav = new ModelAndView("index");
注解方式
在类前面加上@Controller 表示该类是一个控制器
在方法handleRequest 前面加上 @RequestMapping("/index") 表示路径/index会映射到该方法上
注意:不再让IndexController实现Controller接口
@Controller public class IndexController { @RequestMapping("/index") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)throws Exception { ModelAndView mav = new ModelAndView("index"); mav.addObject("message", "Hello Spring MVC"); return mav; } } |
<!-- 自动扫描且只扫描@Controller --> <context:component-scan base-package="controller" /> <!-- 定义JSP文件的位置 --> <bean id="irViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/page/" /> <property name="suffix" value=".jsp" /> </bean> <!-- <bean id="simpleUrlHandlerMapping" --> <!-- class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> --> <!-- <property name="mappings"> --> <!-- <props> --> <!-- <prop key="/index">indexController</prop> --> <!-- </props> --> <!-- </property> --> <!-- </bean> --> <!-- <bean id="indexController" class="controller.IndexController"></bean> --> </beans>
|
接受表单数据,增加
Pojo类Product.java中有3个属性,id、name、price。
addProduct.jsp增加两个input提交表单,到/addProduct。
注意:产品名称input的name要使用name,而不是 product.name
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
<form action="addProduct"> 产品名称 :<input type="text" name="name" value=""><br /> 产品价格: <input type="text" name="price" value=""><br /> <input type="submit" value="增加商品"> </form> |
在ProductController.java中找到/addProduct所对应的方法,
控制器ProductController,准备一个add方法映射/addProduct路径
为add方法准备一个Product 参数,用于接收注入
最后跳转到showProduct页面显示用户提交的数据
注: addProduct.jsp 提交的name和price会自动注入到参数 product里
注: 参数product会默认被当做值加入到ModelAndView 中,相当于:
@Controller public class ProductController { @RequestMapping("/addProduct") public ModelAndView add(Product product) throws Exception { ModelAndView mav = new ModelAndView("showProduct"); return mav; } } |
在WEB-INF/page 目录下创建 showProduct.jsp
用 EL 表达式显示用户提交的名称和价格
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%> 产品名称: ${product.name}<br> 产品价格: ${product.price} |
http://127.0.0.1:8080/springmvc/addProduct.jsp
提交数据,显示结果
客户端跳转
访问页面
http://127.0.0.1:8080/springmvc/jump
结果客户端跳转到了
127.0.0.1:8080/springmvc/index
@Controller public class IndexController { @RequestMapping("/index") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mav = new ModelAndView("index"); mav.addObject("message", "Hello Spring MVC"); return mav; }
@RequestMapping("/jump") public ModelAndView jump() { ModelAndView mav = new ModelAndView("redirect:/index"); return mav; } } |
使用session
IndexController 类中加个check()方法
@RequestMapping("/check") public ModelAndView check(HttpSession session) { Integer i = (Integer) session.getAttribute("count"); if (i == null) i = 0; i++; session.setAttribute("count", i); ModelAndView mav = new ModelAndView("check"); return mav; } |
Check.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
session中记录的访问次数:${count} |
中文问题web.xml中添加过滤器
<filter> <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
上传文件
web.xml
中新增加一段
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
表示允许访问*.jpg。
为什么要加这一段呢? 因为配置springmvc的servlet的时候,使用的路径是"/",导致静态资源在默认情况下不能访问,所以要加上这一段,允许访问jpg。 并且必须加在springmvc的servlet之前
如果你配置spring-mvc使用的路径是/*.do,就不会有这个问题了。
注: 这里仅仅是允许访问jpg,如果你要显示png,gif那么需要额外进行配置
springmvc-servlet.xml
新增加一段配置,开放对上传功能的支持,<!-- 定义上传文件组件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
Upload.jsp
上传页面,需要注意的是form 的两个属性必须提供 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
<form action="uploadImage" method="post" enctype="multipart/form-data"> 选择图片:<input type="file" name="image" accept="image/*" /> <br> <input type="submit" value="上传"> </form> |
UploadedImageFile
中封装MultipartFile类型的字段 image ,用于接受页面的注入
这里的字段 image必须和上传页面upload.jsp中的image
<input type="file" name="image" accept="image/*" />
保持一致
package pojo;
import org.springframework.web.multipart.MultipartFile;
public class UploadedImageFile { MultipartFile image;
public MultipartFile getImage() { return image; } public void setImage(MultipartFile image) { this.image = image; } } |
新建类UploadController 作为上传控制器
准备方法upload 映射上传路径/uploadImage
1. 方法的第二个参数UploadedImageFile 中已经注入好了 image
2. 通过 RandomStringUtils.randomAlphanumeric(10);获取一个随机文件名。 因为用户可能上传相同文件名的文件,为了不覆盖原来的文件,通过随机文件名的办法来规避
3. 根据request.getServletContext().getRealPath 获取到web目录下的image目录,用于存放上传后的文件。
4. 调用file.getImage().transferTo(newFile); 复制文件
5. 把生成的随机文件名提交给视图,用于后续的显示
@Controller public class UploadController {
@RequestMapping("/uploadImage") public ModelAndView upload(HttpServletRequest request, UploadedImageFile file) throws IllegalStateException, IOException { String name = RandomStringUtils.randomAlphanumeric(10); String newFileName = name + ".jpg"; File newFile = new File(request.getServletContext().getRealPath("/image"), newFileName); newFile.getParentFile().mkdirs(); file.getImage().transferTo(newFile);
ModelAndView mav = new ModelAndView("showUploadedFile"); mav.addObject("imageName", newFileName); return mav; } } |
在WEB-INF/page 下新建文件showUploadedFile 显示上传的图片
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<img src="image/${imageName}"/> |
http://127.0.0.1:8080/springmvc/upload.jsp