1.搭建环境及完成Controller和viewer的映射
spring MVC运行机制
解读:一个请求发到DispatcherServlet,然后DispatcherServlet根据URL找到对应的Handlermapping,DispatcherServle再根据Handlermapping找到对应的Controller,Controller处理请求,返回给DispatcherServle 一个视图,DispatcherServle通过ViewResolver处理这个视图,再找到对应的视图返回给浏览器
1.搭建环境
①.在web.xml中配置DispatcherServlet
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
注:只要一访问URL,它就会被这个servlet所捕获
不是根据映射达成的,根据中央处理器
②.在WEB-INF下建立对应的spring配置文件(名字必须为,servler的名字-servlet.xml)
③.配置Handlermapping和ViewResolver
方式1:继承的方式
public class WelcomeController extends AbstractController{
protected ModelAndView handleRequestInternal(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
System.out.println("Welcome!");
return new ModelAndView("welcome");
}
}
spring配置文件
//请求的URL是w.html,就会找到这个Handlermapping
<bean name="/w.html" class="zttc.itat.controller.WelcomeController"></bean>
//配置ViewResolver
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
//视图文件名前的目录
<property name="prefix" value="/WEB-INF/jsp/"></property>
//视图文件后缀名
<property name="suffix" value=".jsp"></property>
</bean>
方式二:注解的方式(推荐)
@Controller
public class HelloController {
//在浏览器请求URL为hello,就会找到这个Handlermapping
@RequestMapping("/hello")
public String Hello(){
System.out.println("hello");
return "hello";
}
}
spring配置文件
<Context:component-scan base-package="zttc.itat.controller"></Context:component-scan>
<mvc:annotation-driven></mvc:annotation-driven>
//配置ViewResolver
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
//视图文件名前的目录
<property name="prefix" value="/WEB-INF/jsp/"></property>
//视图文件后缀名
<property name="suffix" value=".jsp"></property>
</bean>
④.在/WEB-INF/jsp/下建立对应的视图文件
方式一建立welcome.jsp
方式二建立hello.jsp
2.Spring MVC传值
(1).网页将值传给Controller
①.直接在方法中加入形参
//从网页传的参数名为userName时就会传给该方法形参userName
//其他参数的话不会报错,形参userName因没有传值给它而为null
@RequestMapping("/hello")
public String Hello(String userName){
System.out.println(userName);
System.out.println("hello");
return "hello";
}
②.@RequestParam
@RequestMapping("/hello")
//注:加上@RequestParam("userName")
//从网页传过来的参数名必须为 userName,如果不是就会报400
public String Hello(@RequestParam("userName") String userName){
System.out.println(userName);
System.out.println("hello");
return "hello";
}
(2).Controller将值传给网页
①.在方法中加入形参Map<String,Object>context
(传给网页的为一个请求,键为属性名,值为属性值)
@RequestMapping("/hello")
public String Hello(String userName, Map<String,Object>context){
context.put("userName",userName);
return "hello";
}
注:不推荐
②.在方法中加入形参 Model model(传给网页的为一个请求)
@RequestMapping("/hello")
public String Hello(String userName, Model model){
model.addAttribute("userName",userName);
return "hello";
}
注:model.addAttribute(new User()); 相当于model.addAttribute(“user”,new User());
3.Spring MVC实现增删改查
①.添加数据
请求首先发给该方法
@RequestMapping(value = "/add", method = RequestMethod.GET)
public String add(@ModelAttribute("user") User u) {
return "user/add";
}
然后返回该视图给浏览器
//sf:form:将请求带过来的属性(属性名为user,
//表单所填写的数据自动注入到该对象对应的属性中,
//将该对象提交上去,被方法形参中User user接收
//如果该对象最开始各属性有值,那么对应的sf:input的value值为对应属性的值)
<sf:form method="post" modelAttribute="user">
UserName:<sf:input path="userName"></sf:input><sf:errors path="userName"></sf:errors><br/>
PassWord:<sf:password path="passWord"></sf:password><sf:errors path="passWord"></sf:errors><br/>
NickName:<sf:input path="nickName"></sf:input><br/>
email:<sf:input path="emal"></sf:input>
<sf:errors path="emal"></sf:errors><br/>
<input type="submit" value="添加用户">
</sf:form>
将提交的请求交给该方法处理
@RequestMapping(value = "add", method = RequestMethod.POST)
public String add(@Validated User user, BindingResult br) throws IOException {
//BindingResult一定要紧跟验证user,
// 验证结果会放进BindingResult中
// 中间有其他参数传进来就会报错
if (br.hasErrors()) {
return "user/add";
}
users.put(user.getUserName(), user);
//客户端跳转
return "redirect:/user/users";
}
②.删除数据
@RequestMapping(value = "/{userName}/delete", method = RequestMethod.GET)
public String delete(@PathVariable String userName) {
System.out.println("delete userName" + userName);
users.remove(userName);
return "redirect:/user/users";
}
③.修改数据
请求首先发给该方法
@RequestMapping(value = "/{userName}/upDate", method = RequestMethod.GET)
public String update(@PathVariable String userName, Model model) {
model.addAttribute(users.get(userName));
return "user/updata";
}
然后返回该视图给浏览器
//sf:form:将请求带过来的属性(属性名为user,
//表单所填写的数据自动注入到该对象对应的属性中,
//将该对象提交上去,被方法形参中User user接收
//如果该对象最开始各属性有值,那么对应的sf:input的value值为对应属性的值)
<sf:form method="post" modelAttribute="user">
UserName:<sf:input path="userName"></sf:input><sf:errors path="userName"></sf:errors><br/>
PassWord:<sf:password path="passWord"></sf:password><sf:errors path="passWord"></sf:errors><br/>
NickName:<sf:input path="nickName"></sf:input><br/>
email:<sf:input path="emal"></sf:input>
<sf:errors path="emal"></sf:errors><br/>
<input type="submit" value="修改用户">
</sf:form>
将提交的请求交给该方法处理
@RequestMapping(value = "/{userName}/upDate", method = RequestMethod.POST)
public String upDate(@PathVariable String userName, @Validated User user, BindingResult br) {
if (br.hasErrors()) {
System.out.println("错误返回");
return "user/updata";
}
users.put(userName, user);
return "redirect:/user/users";
}
④.查找数据
首先请求发给该方法处理
@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public String Show(@PathVariable String name, Model m) {
System.out.println(name);
m.addAttribute("user", users.get(name));
return "user/show";
}
返回该视图给浏览器
userName:${user.userName}<br/>
passWord:${user.passWord}<br/>
nickName:${user.nickName}<br/>
emal :${user.emal}<br/>
<a href="/user/users">return</a>
补充:
(1).将请求交给controller中对应方法处理
①.浏览器需访问http://localhost:8080/user/add(必须为get请求)
@RequestMapping("/user")
@Controller
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.GET)
public String add(@ModelAttribute("user") User u) {
return "user/add";
}
}
②.浏览器需访问http://localhost:8080/add
@Controller
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.GET)
public String add(@ModelAttribute("user") User u) {
return "user/add";
}
}
③.对于需要带参数的请求,可以用以下注释解决
访问时http://localhost:8080/user/userName/upDate(userName为需要传的参数值,该参数被
@PathVariable String userName,这个userName接收)
需要写的地方:value = "/{userName}/upDate,@PathVariable String userName
@RequestMapping("/user")
@Controller
public class UserController {
@RequestMapping(value = "/{userName}/upDate", method = RequestMethod.GET)
public String update(@PathVariable String userName, Model model) {
System.out.println(userName);
return "user/updata";
}
}
(2).在Controller中方法处理完请求需要返回跳转的视图
①.客户端跳转:将请求发给服务器,服务器处理后在服务端找到对应的文件返回给浏览器
return "redirect:/user/users";
②.服务端跳转:服务器直接在服务端找到对应的文件返回给浏览器
return "user/add";
(3).验证
需导入bean-validator.jar包
需验证的User类属性
@NotEmpty(message = "用户名不能为空")
public String getUserName() {
return userName;
}
@Size(min = 1, max = 10, message = "密码的长度应该在1到10之间")
public String getPassWord() {
return passWord;
}
@Email(message = "邮箱的格式不正确")
public String getEmal() {
return emal;
}
Controller类中,使用验证注解
@RequestMapping(value = "add", method = RequestMethod.POST)
public String add(@Validated User user, BindingResult br){
//BindingResult一定要紧跟验证user,
// 验证结果会放进BindingResult中
// 中间有其他参数传进来就会报错
if (br.hasErrors()) {
//验证出错,服务端跳转
return "user/add";
}
users.put(user.getUserName(), user);
//客户端跳转
return "redirect:/user/users";
}
验证出错跳转的视图
sf:errors:对应属性出错,在网页上打印出对应的message
<sf:form method="post" modelAttribute="user" enctype="multipart/form-data">
UserName:<sf:input path="userName"></sf:input><sf:errors path="userName"></sf:errors><br/>
PassWord:<sf:password path="passWord"></sf:password><sf:errors path="passWord"></sf:errors><br/>
NickName:<sf:input path="nickName"></sf:input><br/>
email:<sf:input path="emal"></sf:input> <sf:errors path="emal"></sf:errors><br/>
<input type="submit" value="添加用户">
</sf:form>
4.Spring MVC 异常处理
当出现异常时,返回浏览器对应的异常视图
配置User异常类
public class UserException extends RuntimeException {
public UserException(String message) {
super(message);
}
}
①.局部异常
// /**
// * 局部异常处理:只能处理这个Controller中的异常
// * @param e
// * @param req
// * @return
// */
@ExceptionHandler(value = UserException.class)
public String handleException(UserException e, HttpServletRequest req) {
req.setAttribute("exception", e);
return "error";
}
②.全局异常
<!--全局异常:使用前需要注释掉Controller中的局部异常,默认将之放到请求中,键为exception-->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="zttc.itat.model.UserException">error</prop>
</props>
</property>
</bean>
出现对应异常时返回的异常视图
<h1>${exception.message}</h1>
补充:将静态文件指定到某个特殊文件夹下统一处理
在spring配置文件中
eg:将web根目录下的文件夹resources指定为特殊文件夹
<!--将静态文件指定到某个特殊的文件夹统一处理:
要不然访问文件将会让DispatcherServlet处理并寻找文件-->
<mvc:resources mapping="/resources/**" location="/resources/"/>
5.Spring MVC文件上传
对应所需的maven依耐
<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>
该视图代码
<sf:form method="post" modelAttribute="user" enctype="multipart/form-data">
UserName:<sf:input path="userName"></sf:input><sf:errors path="userName"></sf:errors><br/>
PassWord:<sf:password path="passWord"></sf:password><sf:errors path="passWord"></sf:errors><br/>
NickName:<sf:input path="nickName"></sf:input><br/>
email:<sf:input path="emal"></sf:input>
<sf:errors path="emal"></sf:errors><br/>
attach:<input type="file" name="attachs">
attach:<input type="file" name="attachs">
attach:<input type="file" name="attachs">
<input type="submit" value="添加用户">
</sf:form>
点击添加用户,将数据交给以下方法处理
@RequestMapping(value = "add", method = RequestMethod.POST)
public String add(@Validated User user, BindingResult br,@RequestParam("attachs") MultipartFile[] attachs,HttpServletRequest req) throws IOException {
for (MultipartFile attach:attachs) {
if(attach.isEmpty()){
continue;
}
System.out.println(attach.getName() + "," + attach.getOriginalFilename() + "," + attach.getContentType());
String realPath = req.getSession().getServletContext().getRealPath("/resours/upLoad");
System.out.println(realPath);
File file = new File(realPath + "/" + attach.getOriginalFilename());
FileUtils.copyInputStreamToFile(attach.getInputStream(), file);
}
//BindingResult一定要紧跟验证user,
// 验证结果会放进BindingResult中
// 中间有其他参数传进来就会报错
if (br.hasErrors()) {
return "user/add";
}
users.put(user.getUserName(), user);
//客户端跳转
return "redirect:/user/users";
}
文件保存路径为realPath