1、spring mvc
(1)、spring mvc都为我们做了什么
- Controller为中心完成对系统流程的控制管理
- 从请求中搜集数据
- 对传入的参数进行验证
- 将结果返回给视图
- 针对不同的视图提供不同的解决方案
- 针对jsp视图技术提供标签库:JSTL标签+EL表达式
- 拦截器
- 上传文件
(2)、spring mvc的核心组件
- DispatcherServlet:中央控制器,把请求给转发到具体的控制类
- Controller:具体处理请求的控制器
- handlerMapping:映射处理器,负责映射中央处理器转发给controller时的映射策略
- ModelAndView:服务层返回的数据和视图层的封装类
- ViewResolver & View:视图解析器,解析具体的视图
- Interceptors :拦截器,负责拦截我们定义的请求然后做
红色标注的部分是要我们自己写的类,黑色部分是调用已经存在的类。
(3)、mvc的模式
(4)、spring mvc的工作流程
(5)、spring mvc的hello详解
A、配置DispatcherServlet
web.xml
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<!-- 中央控制器-->
<servlet>
<!-- 中央控制器的名字,此处的名字要与springmvc的核心配置文件名字一致-->
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 响应一切以.do的页面-->
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
创建springmvc的核心配置文件
文件的命名规则:中央控制器(servlet的名称)的名称+“-servlet.xml”
默认位置:WEB-INF下
配置:controller和视图解析器
<?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.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd ">
<!-- 需要配置controller,handlerMapping,ViewResolver, interceptor -->
<!-- 映射处理器之间是独立的,不相互影响 -->
<!-- 默认的映射处理器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 简单url的映射处理器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello1.do">testController</prop>
</props>
</property>
</bean>
<!-- 控制器的类名映射处理器 -->
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"></bean>
<!-- 使用默认的映射处理器来映射controller -->
<bean id="testController" name="/hello.do" class="cn.itcast.springmvc.TestController"></bean>
<!-- 前缀+ viewName +后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- webroot到某一指定的文件夹的路径 -->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!-- 视图名称的后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
以上使用配置文件的方式实现的。貌似并不推荐。只是明白原理就好。
2、spring mvc实例演练
- @Service用于标注业务层组件
- @Controller用于标注控制层组件(如struts中的action)
- @Repository用于标注数据访问组件,即DAO组件
- @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
intellij代码说明:
查看注释:Win: Ctrl+Q, Mac: Control+J
补齐方法调用: tab,如果方法有参数,光标会自动定位在小括号内,这个时候,使用commond+P或者Alt+P可以查看参数信息;如果没有参数,直接定位在()后;调用完毕,不需要再定位光标,直接 shift+command+Enter (win: Shift+Ctrl+Enter) 会自动补齐分号“;”,并自动定位到下一行
补齐方法调用: tab,如果方法有参数,光标会自动定位在小括号内,这个时候,使用commond+P或者Alt+P可以查看参数信息;如果没有参数,直接定位在()后;调用完毕,不需要再定位光标,直接 shift+command+Enter (win: Shift+Ctrl+Enter) 会自动补齐分号“;”,并自动定位到下一行
注解方式参数,接收参数的方式:
- HttpServletRequest可以直接定义在参数的列表,可以使用
- 在参数列表上直接定义要接收的参数名称,只要参数名称能匹配的上就能接收所传过来的数据, 可以自动转换成参数列表里面的类型,注意的是值与类型之间是可以转换的
- 数据写到页面,方法的返回值采用ModelAndView, new ModelAndView("index", map);,相当于把结果数据放到request里面
- 在参数列表中直接定义Model,model.addAttribute("p", person);把参数值放到request类里面去,建议使用
- Ajax调用springmvc的方法:直接在参数的列表上定义PrintWriter,out.write(result);把结果写到页面,建议使用的
- 请求方式的指定:@RequestMapping( method=RequestMethod.POST )可以指定请求方式,前台页面就必须要以它制定好的方式来访问,否则出现405错误
- 重定向:controller内部重定向,redirect:加上同一个controller中的requestMapping的值,controller之间的重定向:必须要指定好controller的命名空间再指定requestMapping的值,redirect:后必须要加/,是从根目录开始
示例代码:
/**
*
* desc:方法的返回值是ModelAndView中的viewName
*/
@RequestMapping("/hello.do")//用来访问控制层的方法的注解
public String hello(){
System.out.println("hello springmvc with annotation");
return "jsp1/index";
}
/**
*
* desc:HttpServletRequest可以直接定义在参数的列表,可以使用
*/
@RequestMapping("/toPerson.do")
public String toPerson(HttpServletRequest request){
String result = request.getParameter("name");
System.out.println(result);
return "jsp1/index";
}
/**
*
* desc:在参数列表上直接定义要接收的参数名称,只要参数名称能匹配的上就能接收所传过来的数据,
* 可以自动转换成参数列表里面的类型,注意的是值与类型之间是可以转换的
*/
@RequestMapping("/toPerson1.do")
public String toPerson1(String name, Integer age, String address, Date birthday){
System.out.println(name + " "+ age + " "+ address + " " +birthday);
return "jsp1/i.ndex";
}
/**
*
* desc:注册时间类型的属性编辑器
*/
@InitBinder
public void initBinder(ServletRequestDataBinder binder){
binder.registerCustomEditor(Date.class,
new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
/**
*
* desc:传递的参数的名字必须要与实体类的属性set方法后面的字符串匹配的上才能接收到参数,首字符的大小写不区分
* 请求中传的参数只要是能和参数列表里面的变量名或者实体里面的set后面的字符串匹配的上就能接收到
*/
@RequestMapping("/toPerson2.do")
public String toPerson2(Person person, User user){
System.out.println(person);
System.out.println(user);
return "jsp1/index";
}
/**
*
* desc:对数组的接收
*/
@RequestMapping("/toPerson3.do")
public String toPerson3(String[] name){
for(String result : name){
System.out.println(result);
}
return "jsp1/index";
}
2012-22-10会自动转换成2013-10-10
JSP中该如何显示呢?
代码如下:
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<h1>${p.name }</h1>
<h1>${p.age }</h1>
<h1>${p.address }</h1>
<h1><fmt:formatDate value="${p.birthday }" pattern="yyyy-MM-dd"/> </h1>
注意上面写的Date类型的显示格式的自定义标签
ajax (ajax开发)
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。
AJAX = 异步 JavaScript和XML(标准通用标记语言的子集)。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。
AJAX = 异步 JavaScript和XML(标准通用标记语言的子集)。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。
/**
*
* desc:方法的返回值采用ModelAndView, new ModelAndView("index", map);
* ,相当于把结果数据放到request里面
*/
@RequestMapping("/toPerson4.do")
public ModelAndView toPerson4() throws Exception{
Person person = new Person();
person.setName("james");
person.setAge(28);
person.setAddress("maami");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse("1985-04-22");
person.setBirthday(date);
Map<String, Object> map = new HashMap<String, Object>();
map.put("p", person);
return new ModelAndView("index", map);
}
/**
*
* desc:直接在方法的参数列表中来定义Map,这个Map即使ModelAndView里面的Map,
* 由视图解析器统一处理,统一走ModelAndView的接口
* 也不建议使用
*/
@RequestMapping("/toPerson5.do")
public String toPerson5(Map<String, Object> map) throws Exception{
Person person = new Person();
person.setName("james");
person.setAge(28);
person.setAddress("maami");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse("1985-04-22");
person.setBirthday(date);
map.put("p", person);
return "index";
}
/**
*
* desc:在参数列表中直接定义Model,model.addAttribute("p", person);把参数值放到request类里面去,建议使用
*/
@RequestMapping("/toPerson6.do")
public String toPerson6(Model model) throws Exception{
Person person = new Person();
person.setName("james");
person.setAge(28);
person.setAddress("maami");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = format.parse("1985-04-22");
person.setBirthday(date);
//把参数值放到request类里面去
model.addAttribute("p", person);
return "index";
}
/**
*
* desc:ajax的请求返回值类型应该是void,参数列表里直接定义HttpServletResponse,
* 获得PrintWriter的类,最后可把结果写到页面
* 不建议使用
*/
@RequestMapping("/ajax.do")
public void ajax(String name, HttpServletResponse response){
String result = "hello " +name;
try {
response.getWriter().write(result);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* desc:直接在参数的列表上定义PrintWriter,out.write(result);把结果写到页面,建议使用的
*/
@RequestMapping("/ajax1.do")
public void ajax1(String name, PrintWriter out){
String result = "hello " +name;
out.write(result);
}
@RequestMapping("/toAjax.do")
public String toAjax(){
return "ajax";
}
@RequestMapping("/toForm.do")
public String toForm(){
return "form";
}
/**
*
* desc:controller内部重定向,redirect:加上同一个controller中的requestMapping的值
*/
@RequestMapping("/redirectToForm.do")
public String redirectToForm(){
return "redirect:toForm.do";
}
/**
*
* desc:controller之间的重定向:必须要指定好controller的命名空间再指定requestMapping的值,
* redirect:后必须要加/,是从根目录开始
*/
@RequestMapping("/redirectToForm1.do")
public String redirectToForm1(){
return "redirect:/test1/toForm.do";
}
/**
*
* desc:@RequestMapping( method=RequestMethod.POST )可以指定请求方式,前台页面就必须要以它制定好的方式来访问,否则出现405错误
*/
@RequestMapping(value="/toPerson7.do", method=RequestMethod.POST )
public String toPerson7(Person person){
System.out.println(person);
return "jsp1/index";
}
3、spring mvc文件的上传下载
pom.xml加入两个依赖:io与FileUpload
<!-- 文件的上传下载-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
需要在spring的servlet.xml文件中加入以下配置
<!-- id="multipartResolver"必须是multipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- maxUploadSize:文件上传的最大值以byte为单位 -->
<property name="maxUploadSize" value="1024000"></property>
</bean>
表单jsp:
<html>
<head>
<title></title>
</head>
<body>
<form action="/toForm1.do" method="post" enctype="multipart/form-data">
文件:<input type="file" name="pic"><br>
<input type="submit" value="提交"><br>
</form>
</body>
</html>
Controller:
@RequestMapping(value="/toPerson8.do")
public String toPerson8(Person person,HttpServletRequest request) throws Exception{
//第一步转化request
MultipartHttpServletRequest rm = (MultipartHttpServletRequest) request;
//获得文件
CommonsMultipartFile cfile = (CommonsMultipartFile) rm.getFile("pic");
//获得文件的字节数组
byte[] bfile = cfile.getBytes();
String fileName = "";
//获得当前时间的最小精度
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
fileName = format.format(new Date());
//获得三位随机数
Random random = new Random();
for(int i = 0; i < 3; i++){
fileName = fileName + random.nextInt(9);
}
//获得原始文件名
String origFileName = cfile.getOriginalFilename();
//XXX.jpg
String suffix = origFileName.substring(origFileName.lastIndexOf("."));
//拿到项目的部署路径
String path = request.getSession().getServletContext().getRealPath("/");
//定义文件的输出流
OutputStream out = new FileOutputStream(new File(path+"/upload/"+fileName+suffix));
out.write(bfile);
out.flush();
out.close();
return "jsp1/index";
}
4、spring mvc拦截器
(1)、PreHandler:
前置拦截主要用于对权限的拦截
执行时机:在执行controller之前来执行
返回值类型:boolean:true代表放行可以访问controller,false不可以访问controller
执行时机:在执行controller之前来执行
返回值类型:boolean:true代表放行可以访问controller,false不可以访问controller
(2)、PostHandler:
后置拦截器
执行时机:controller执行完,视图解析器没有把视图解析成页面,
对视图做统一的修改,主要体现在Model上
例如:在modleAndView中加入头尾
(3)、AfterHandler:
执行时机:视图已经被解析完毕,类似try catch 后的finally
监控方面,追踪错误异常,存入库中
5、修改spring mvc配置文件的位置
我的文件位置如下:
在web.xml文件中,配置如下:
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring MVC Application</display-name>
<!-- 中央控制器-->
<servlet>
<!-- 中央控制器的名字,此处的名字要与springmvc的核心配置文件名字一致-->
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 响应一切以.do的页面-->
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>