Spring MVC
1.结构最清晰的MVC Model2实现
2.Controller
3.ModelAndView
1.HTTP请求 SpringMVC核心是前端控制器DispatcherServlet 在web.xml <servlet-name>-servlet.xml配置
2.HandlerMapping:通过配置去找Handler(Controller)
3.Handler:处理器 调用service方法进行业务处理
4.返回数据ModelAndView(增删改查)逻辑视图名 并不是真正的视图对象
5.ViewResolver :视图解析器 DispatcherServlet借助视图解析器把逻辑视图名解析成真正的视图对象。
6.获得model数据模型放到View视图中(JSP/JSTL/PDF...)
7.HTTP响应给客户端(用户)
springMVC在web.xml配置
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup><!--优先启动 -->
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
springMVC-servlet.xml核心配置文件/WEB-INF/springMVC-servlet.xml
<!-- 通过bean的name,完成url映射 -->
<bean name="/springMVC.html" class="cn.bdqn.controller.HelloController"/>
name是用户请求的url 通过class找到controller controller返回modelandwiew 通过视图解析器解析返回view视图给用户。
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
我要放到resource里面 在web.xml 配置
<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:springMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup><!--优先启动 -->
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
注解的方式:DefaultAnnotationHandlerMapping
<!--使用annotation方式,完成映射-->
<!--使用annotation方式,完成映射-->
<!--让spring扫描包下的所有的类,让标注spring注解的类生效 -->
<context:component-scan base-package="cn.bdqn.controller"></context:component-scan>
<mvc:annotation-driven/>
通过@RequestMapping(value = "/hello")
通过@RequestMapping的value匹配用户请求的url找到controller类的xxx方法 再执行
@Controller
public class WelcomController {
// 通过@RequestMapping的value匹配用户请求的url找到controller类的hello()方法 再执行
@RequestMapping(value = "/hello")
public String hello() {
System.out.println("hello spring!!!");
return "hello";// 逻辑视图名
}
}
视图解析器:
1.将逻辑视图的名字与JSP等视图技术进行匹配
2.InternalResourceViewResolver
在web应用程序的War文件中查找视图模板,视图模板的路径根据加完前缀和后缀的逻辑视图名称来确定
prefix
suffix
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
参数的传递-1
[email protected]
2.直接通过函数参数传值
@RequestMapping(value = "/hello")
public String hello(@RequestParam(value = "username") String username) {
System.out.println("hello spring!!! username----->>>" + username);
return "hello01";// 逻辑视图名
}
@RequestParam(value = "username")请求中的参数必须写
@RequestMapping(value = "/hello")
public String hello(String name) {
System.out.println("hello spring!!! name----->>>" + name);
return "hello01";// 逻辑视图名
}
通过url传来的参数 在后台直接能取到。但是参数名必须与方法传递的参数名一致 否则获取不到
@RequestMapping(value = "/hello")
// 通过model.addAttribute("username",name)放进作用域。通过EL表达式取出数据
public String hello(String name, Model model) {
model.addAttribute("username", name);
System.out.println("hello spring!!! name----->>>" + name);
return "hello01";// 逻辑视图名
}
@RequestMapping(value = "/hello")
// 通过model.addAttribute("username",name)放进作用域。通过EL表达式取出数据
public ModelAndView hello(String name) {
System.out.println(name);
ModelAndView model = new ModelAndView();
model.setViewName("hello01");// 逻辑 视图名
model.addObject("username", name);
return model;
}
@RequestMapping(value = "/hello")
// 通过model.addAttribute("username",name)放进作用域。通过EL表达式取出数据
public ModelAndView hello(String name) {
System.out.println(name);
ModelAndView model = new ModelAndView();
model.setViewName("hello01");// 逻辑 视图名
model.addObject(name);// 在前台取值${string} 就是取到value的数据类型
return model;
}
@RequestMapping(value = "/hello")
// 通过model.addAttribute("username",name)放进作用域。通过EL表达式取出数据
public String hello(String name, Map<String, Object> model) {
System.out.println(name);
model.put("name", name);// 在前台取值${string} 就是取到value的数据类型
return "hello01";
}
参数的传递-2
通过Map<Spring,Object>
Model
controller是单例的。
REST风格 并不是rest技术
1.Representational State Transfer表达性状态转移
2.传统的查、改、删的URL与REST风格的增删改URL对比
/userview.action?id=12 VS /user/12
/userdelete.action?id=12 vs /user/12/delete
/userdelete.action?id=12 vs /user/12/update
3.请求方式
GET 读取数据 查询
POST 添加 提交
DELETE 删除
PUT 修改
他强调的是一个资源可以对应多种视图
创建POJO-User类
HashMap
@RequestMapping(value="/userlist",method=RequestMethod.GET)
@Controller
@RequestMapping(value = "/user")
public class UserController {
private static Map<String, Object> map = new HashMap<String, Object>();
// 通过静态代码块赋值
static {
map.put("1", new User(1, "张三", "123456", "[email protected]"));
map.put("2", new User(2, "李四", "123456", "[email protected]"));
map.put("3", new User(3, "王五", "123456", "[email protected]"));
}
@RequestMapping(value = "/list",method = RequestMethod.GET)
public String list(Model model) {
model.addAttribute("map", map);
return "user/userlist";
}
}
用户列表:<br>
<c:forEach var="ul" items="${map }">
id:${ul.value.id }------
userName:${ul.value.userName }------
password:${ul.value.password }------
email:${ul.value.email }<br>
</c:forEach>
@RequestMapping(value = "/list",method = RequestMethod.GET)
public String userList(HttpServletRequest request) {
List<User> list = new ArrayList<User>();
list.add(new User(1, "张三", "123456", "[email protected]"));
list.add(new User(2, "李四", "123456", "[email protected]"));
list.add(new User(3, "王五", "123456", "[email protected]"));
request.setAttribute("list", list);
return "user/userlist";
}
用户列表:<br>
<c:forEach var="user" items="${list }">
id:${user.id }------
userName:${user.userName }------
password:${user.password }------
email:${user.email }<br>
</c:forEach>
model的作用域是个request级别
异常处理
JSR303 是一套JavaBean参数校验的标准,它定义了很多常用的校验注解,我们可以直接将这些注解加在我们JavaBean的属性上面,就可以在需要校验的时候进行校验了。注解如下:
@NotNull 注解元素必须是非空
@Null 注解元素必须是空
@Digits 验证数字构成是否合法
@Future 验证是否在当前系统时间之后
@Past 验证是否在当前系统时间之前
@Max 验证值是否小于等于最大指定整数值
@Min 验证值是否大于等于最小指定整数值
@Pattern 验证字符串是否匹配指定的正则表达式
@Size 验证元素大小是否在指定范围内
@DecimalMax 验证值是否小于等于最大指定小数值
@DecimalMin 验证值是否大于等于最小指定小数值
@AssertTrue 被注释的元素必须为true
@AssertFalse 被注释的元素必须为false
Hibernate validator 在JSR303的基础上对校验注解进行了扩展,扩展注解如下:
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内
<!-- 处理字符编码filter -->
<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>
@RequestMapping(value = "/addSave", method = RequestMethod.POST)
public String addSave(@Validated User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "user/add";// 如果用户输入不正确 就会返回add 重新输入
}
map.put(user.getId() + "", user);
return "redirect:/user/list";
}
/**
* REST风格
* @param id
* @param model
* @return
*/
@RequestMapping(value = "/view/{id}", method = RequestMethod.GET)
public String view(@PathVariable String id, Model model) {
System.out.println(id);
model.addAttribute("user", map.get(id));
return "user/view";
}
/**
* 先回显 在修改
* @param id
* @param user
* @return
*/
@RequestMapping(value = "/{id}/update", method = RequestMethod.GET)
public String update(@PathVariable String id, Model model) {
model.addAttribute(map.get(id));
return "user/update";
}
/**
* 修改@PathVariable REST风格获取参数 {id}入参的形式
* @param id
* @param user
* @param bindingResult
* @return
*/
@RequestMapping(value = "/{id}/update", method = RequestMethod.POST)
public String update(@PathVariable String id, @Validated User user,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "user/update";
}
map.put(user.getId() + "", user);
return "redirect:/user/list";
}
@RequestMapping(value = "/{id}/delete", method = RequestMethod.GET)
public String detele(@PathVariable String id) {
map.remove(id);// 删除
return "redirect:/user/list";
}
1.异常处理
1.局部异常处理:@ExceptionHandler
2.全局异常处理:SimpleMappingExceptionResolver
2.使用Servlet API对象作为入参
1.HttpSession
2.HttpServletRequest
3.HttpServletResponse
map<key,value>
hash表的结构
1 map<object,object>
map key="t01" value的内存地址
<!--全局异常处理:SimpleMappingExceptionResolver-->
<!-- 全局异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="cn.bdqn.bean.UserException">error</prop>
</props>
</property>
</bean>
前台获取异常信息
${exception.message } <br>
<!--配置静态文件访问springMVC中无法访问静态文件,需要映射成URL路径进行访问 -->
<mvc:resources location="/statics/" mapping="/statics/**"/>
页面需要引入<link href=<%=request.getContextPath() %>/statics/css/main.css rel="stylesheet" style="text/css"/>
处理文件上传-单文件上传
导包:commons-fileupload-1.2.2.jar、commons-io-2.4.jar
在添加页面表单中添加一个文件上传域
修改UserController的add()方法以接收上传的文件
在Spring中配置multipart文件处理器
文件上传
<!--配置文件上传 MultiPartResovler -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1000000"/>
</bean>
@RequestMapping(value = "/addSave", method = RequestMethod.POST)
public String addSave(@Validated User user, BindingResult bindingResult,
@RequestParam MultipartFile[] attachs, HttpServletRequest request) {
if (bindingResult.hasErrors()) {
return "user/add";// 如果用户输入不正确 就会返回add 重新输入
}
// 获取
String upload = request.getSession().getServletContext()
.getRealPath("/statics/upload");
// 非空验证File.separator自动识别"/"
try {
// 多文件上传
for (MultipartFile attach : attachs) {
if (!attach.isEmpty()) {
File file = new File(upload + File.separator
+ attach.getOriginalFilename());
FileUtils.copyInputStreamToFile(attach.getInputStream(),
file);
}
}
} catch (IOException e) {
e.printStackTrace();
}
map.put(user.getId() + "", user);
return "redirect:/user/list";
}
添加页面:</br>
<!-- 不写action 默认提交到add -->
<fm:form modelAttribute="user" action="user/addSave" method="post" enctype="multipart/form-data">
id:<fm:input path="id"/></br>
userName:<fm:input path="userName"/><fm:errors path="userName"/></br>
password:<fm:input path="password"/><fm:errors path="password"/></br>
email:<fm:input path="email"/><fm:errors path="email"/></br>
attach:<input type="file" name="attachs"/></br>
<input type="file" name="attachs"/></br>
<input type="file" name="attachs"/></br>
<input type="submit" value="提交" >
</fm:form>
Spring MVC返回JSON数据
1.导入jar包:jackson-all-1.9.11.jar
2.RequestMapping(value="/{userName}",method=RequestMethod.GET,param="json)
3.ResponseBody
// params="json"的意思:访问view 这个方法的时候,必须有一个参数json
@RequestMapping(value = "/view/{id}", method = RequestMethod.GET, params = "json")
@ResponseBody
public User view(@PathVariable String id) {
return map.get(id);
}