SpringMVC
第一章
1.1 三层架构
- 表现层:web层,用来和客户端进行数据交互的,一般采用MVC的设计模式
- 业务层:处理公司具体的业务逻辑的
- 持久层:操作数据库的
1.2 MVC模型
- Model:用来进行数据封装
- View:用来展示数据给用户
- Controller:用来接收用户请求,整个流程的控制器,进行数据校验等
1.3 SpringMVC的优势
- 清晰的角色划分
- 前端控制器(DispatcherServlet)
- 控制流程的中心,有它调用其他组件处理用户的请求,解耦
- 请求到处理器映射(HandlerMapping)
- 负责根据用户请求找到Handler即处理器,SpringMVC 提供了不同的映射器实现不同的 映射方式,例如:配置文件方式,实现接口方式,注解方式等
- 处理器(Handler)
- 由DispatcherServlet把用户请求转发到Handler,由Handler对具体的用户请求进行处理
- 处理器适配器(HandlerAdapter)
- 充当接口作用
- 视图解析器(ViewResolver)
- 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名 即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户
- 视图(view)
- SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView 等。我们最常用的视图就是 jsp
- 处理器或页面控制器(Controller)
- 验证器( Validator)
- 命令对象(Command 请求参数绑定到的对象就叫命令对象)
- 表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)
- 前端控制器(DispatcherServlet)
- 分工明确,容易扩展
- 可使用命令对象直接作为业务对象
- 和Spring无缝集成
- 可适配
- 可定制性
1.4 SpringMVC入门案例
通过Maven创建web工程,引入依赖
配置核心的控制器(在web.xml中配置DispatcherServlet)
<servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 配置servlet启动时加载对象 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
编写springmvc.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 开启注解扫描 --> <context:component-scan base-package="cn.itcast"/> <!-- 视图解析器对象 --> <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> <!--配置自定义类型转换器--> <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="cn.itcast.utils.StringToDateConverter"/> </set> </property> </bean> <!-- 开启SpringMVC框架注解的支持 --> <mvc:annotation-driven conversion-service="conversionService"/> <!-- SpringMVC的各个组件中,处理器映射器,处理器适配器,视图解析器成为SpringMVC三大组件,配置了上面这个标签,自动加载RequestMappingHandlerMapping (处理映射器)和 RequestMappingHandlerAdapter ( 处 理 适 配 器 ) --> </beans>
编写index.jsp和HelloController控制器类
index.jsp
<body> <h3>入门案例</h3> <a href="${ pageContext.request.contextPath }/hello">入门案例</a> </body>
HelloController
@Controller public class HelloController { /** * 接收请求 * @return */ @RequestMapping(path="/hello") public String sayHello() { System.out.println("Hello SpringMVC!!"); return "success"; } }
在web-INF目录下创建pages文件夹,编写success.jsp的成功页面
<body> <h3>入门成功</h3> </body>
测试
1.5 RequestMapping注解
@Controller("accountController") @RequestMapping("/account") public class AccountController { @RequestMapping("/findAccount") public String findAccount() { System.out.println("查询了账户。。。。"); return "success"; } //method属性:限定提交方式 @RequestMapping(value="/saveAccount",method=RequestMethod.POST) public String saveAccount() { System.out.println("保存了账户"); return "success"; } //限定了参数,<a href="account/removeAccount?accountName=aaa&money>100">可访问 @RequestMapping(value="/removeAccount",params= {"accountName","money>100"}) public String removeAccount() { System.out.println("删除了账户"); return "success"; } }
<!-- jsp中的使用 --> <body> <!-- 第一种访问方式 --> <a href="${pageContext.request.contextPath}/account/findAccount"> 查询账户 </a> <br/> <!-- 第二种访问方式 --> <a href="account/findAccount"> 查询账户 </a> </body>
1.6 请求参数的绑定
<a href="account/findAccount?accountId=10">查询账户</a> //会自动将请求参数accountId=10作为方法的参数传入 @RequestMapping("/findAccount") public String findAccount(Integer accountId) { System.out.println("查询了账户。。。。"+accountId); return "success"; }
- 控制器方法中的形参支持的数据类型
- 基本类型(加String类型)
- 要求请求参数名称和控制器中方法的形参名称严格一致
- POJO类型参数(实体类,相关联的实体类)
- 要求表单中的参数名称和POJO类的属性名称保持一致,并且控制器方法的参数类型是POJO类型
- 数组和集合类型参数
- 基本类型(加String类型)
public class Account implements Serializable { private Integer id; private String name; private Float money; private Address address; //getters and setters } public class Address implements Serializable { private String provinceName; private String cityName; //getters and setters } public class User implements Serializable { private String username; private String password; private Integer age; private List<Account> accounts; private Map<String,Account> accountMap; //getters and setters } //在controller中 @RequestMapping("/saveAccount") public String saveAccount(Account account) { System.out.println("保存了账户。。。。"+account); return "success"; } @RequestMapping("/updateAccount") public String updateAccount(User user) { System.out.println("更新了账户。。。。"+user); return "success"; }
<form action="account/saveAccount" method="post"> 账户名称:<input type="text" name="name" ><br/> 账户金额:<input type="text" name="money" ><br/> 账户省份:<input type="text" name="address.provinceName" ><br/> 账户城市:<input type="text" name="address.cityName" ><br/> <input type="submit" value=" 保存 "> </form> <form action="account/updateAccount" method="post"> 用户名称:<input type="text" name="username" ><br/> 用户密码:<input type="password" name="password" ><br/> 用户年龄:<input type="text" name="age" ><br/> 账户 1 名称:<input type="text" name="accounts[0].name" ><br/> 账户 1 金额:<input type="text" name="accounts[0].money" ><br/> 账户 2 名称:<input type="text" name="accounts[1].name" ><br/> 账户 2 金额:<input type="text" name="accounts[1].money" ><br/> 账户 3 名称:<input type="text" name="accountMap['one'].name" ><br/> 账户 3 金额:<input type="text" name="accountMap['one'].money" ><br/> 账户 4 名称:<input type="text" name="accountMap['two'].name" ><br/> 账户 4 金额:<input type="text" name="accountMap['two'].money" ><br/> <input type="submit" value=" 保存 "> </form>
1.7 请求参数乱码问题
post 请求方式: 在 web.xml 中配置一个过滤器 <!-- 配置 springMVC 编码过滤器 --> <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> <!-- 启动过滤器 --> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <!-- 过滤所有请求 --> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 在 springmvc 的配置文件中可以配置,静态资源不过滤: <!-- location 表示路径,mapping 表示文件,**表示该目录下的文件以及子目录的文件 --> <mvc:resources location="/css/" mapping="/css/**"/> <mvc:resources location="/images/" mapping="/images/**"/> <mvc:resources location="/scripts/" mapping="/javascript/**"/> get 请求方式: tomacat 对 GET和 POST 请求处理方式是不同的,GET请求的编码问题,要改 tomcat 的 server.xml 配置文件,如下: <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/> 改为: <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/> 如果遇到 ajax 请求仍然乱码,请把: useBodyEncodingForURI="true"改为 URIEncoding="UTF-8" 即可。
1.8 自定义类型转换器
- 使用情况
<a href="account/deleteAccount?date=2018-01-01">根据日期删除账户</a>
@RequestMapping("/deleteAccount") public String deleteAccount(String date) { System.out.println("删除了账户。。。。"+date); return "success"; }//此时可能会报错,因为格式不匹配,自动转换要求不匹配
- 使用步骤
第一步:定义一个类,实现 Converter 接口,该接口有两个泛型。 public interface Converter<S, T> {//S:表示接受的类型,T:表示目标类型 /** * 实现类型转换的方法 */ @Nullable T convert(S source); } public class StringToDateConverter implements Converter<String, Date> { /** * 用于把 String 类型转成日期类型 */ @Override public Date convert(String source) { DateFormat format = null; try { if(StringUtils.isEmpty(source)) { throw new NullPointerException("请输入要转换的日期"); } format = new SimpleDateFormat("yyyy-MM-dd"); Date date = format.parse(source); return date; } catch (Exception e) { throw new RuntimeException("输入日期有误"); } } }
第二步:在 spring配置文件中配置类型转换器 <!-- 配置类型转换器工厂 --> <bean id="converterService" class="org.springframework.context.support.ConversionServiceFactoryBean"> <!-- 给工厂注入一个新的类型转换器 --> <property name="converters"> <array> <!-- 配置自定义类型转换器,将自定义的转换器也加入其中 --> <bean class="com.itheima.web.converter.StringToDateConverter"></bean> </array> </property> </bean> 第三步:在 annotation-driven标签中引用配置的类型转换服务 <!-- 引用自定义类型转换器 --> <mvc:annotation-driven conversion-service="converterService"></mvc:annotation-driven>
1.9 使用ServletAPI对象作为方法参数
<a href="account/testServletAPI">测试访问 ServletAPI</a>
@RequestMapping("/testServletAPI") public String testServletAPI(HttpServletRequest request, HttpServletResponse response, HttpSession session) { System.out.println(request); System.out.println(response); System.out.println(session); return "success"; }
1.10 常用注解
- RequestParam:把求情中指定名称的参数给控制器中的形参赋值
- 属性
- value:请求参数的名称
- required:请求参数中是否必须提供此参数。默认值:true,表示必须提供,不提供则报错
- RequestBody:用于获取请求体内容。直接使用得到是 key=value&key=value...结构的数据。 get 请求方式不适用。
- 属性
- required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值 为 false,get 请求得到是 null。
- PathVaribale :用于绑定 url 中的占位符。
- value:用于指定 url 中占位符名称
- required:是否必须提供占位符。
- RequestHeader :用于获取请求消息头
- 属性
- value:提供消息头名称
- required:是否必须有此消息头
- CookieValue :用于把指定 cookie 名称的值传入控制器方法参数。
- value:指定 cookie 的名称。
- required:是否必须有此 cookie
<a href="springmvc/useRequestParam?name=test">requestParam 注解</a> post 请求 jsp代码: <!-- request body 注解 --> <form action="springmvc/useRequestBody" method="post"> 用户名称:<input type="text" name="username" ><br/> 用户密码:<input type="password" name="password" ><br/> 用户年龄:<input type="text" name="age" ><br/> <input type="submit" value=" 保存 "> </form> get 请求 jsp代码: <a href="springmvc/useRequestBody?body=test">requestBody 注解 get 请求</a> <a href="springmvc/usePathVariable/100">pathVariable 注解</a> <a href="springmvc/useRequestHeader">获取请求消息头</a> <a href="springmvc/useCookieValue">绑定 cookie 的值</a>
@RequestMapping("/useRequestParam") public String useRequestParam(@RequestParam("name")String username, @RequestParam(value="age",required=false) Integer age){ System.out.println(username+","+age); return "success"; } @RequestMapping("/useRequestBody") public String useRequestBody(@RequestBody(required=false) String body){ System.out.println(body); return "success"; } @RequestMapping("/usePathVariable/{id}") public String usePathVariable(@PathVariable("id") Integer id){ System.out.println(id); return "success"; } @RequestMapping("/useRequestHeader") public String useRequestHeader( @RequestHeader(value="Accept-Language", required=false)String requestHeader){ System.out.println(requestHeader); return "success"; } @RequestMapping("/useCookieValue") public String useCookieValue( @CookieValue(value="JSESSIONID",required=false) String cookieValue){ System.out.println(cookieValue); return "success"; }
- ModelAttribute :若一个方法被ModelAttribute修饰后,进行处理器请求方法之前它会被执行
<form action="springmvc/updateUser" method="post"> 用户名称:<input type="text" name="username" ><br/> //输入cgx 用户年龄:<input type="text" name="age" ><br/> //输入23 <input type="submit" value=" 保存 "> </form>
@ModelAttribute public User showModel(User user) { User abc = findUserByName(username); System.out.println("执行了 showModel 方法"+abc); return abc; }//username=cgx,password=123456,age=19,会将对象传递给下面的方法参数中 方式一:带返回值 @RequestMapping("/updateUser") public String testModelAttribute(User user) { //会根据表单的值修改user对象内容。 System.out.println("控制器中处理请求的方法:修改用户:"+user); return "success"; }//username=cgx,password=123456,age=23 private User findUserByName(String username) { User user = new User(); user.setUsername(username); user.setAge(19); user.setPassword("123456"); return user; } 方式二:不带返回值 @ModelAttribute public void showModel(String username,Map<String,User> map) { //模拟去数据库查询 User user = findUserByName(username); System.out.println("执行了 showModel 方法"+user); map.put("abc",user); } @RequestMapping("/updateUser") public String testModelAttribute(@ModelAttribute("abc")User user) { System.out.println("控制器中处理请求的方法:修改用户:"+user); return "success"; }
- SessionAttribute:用于多次执行控制器方法间的参数共享
<!-- SessionAttribute 注解的使用 --> <a href="springmvc/testPut">存入 SessionAttribute</a> <hr/> <a href="springmvc/testGet">取出 SessionAttribute</a> <hr/> <a href="springmvc/testClean">清除 SessionAttribute</a>
@Controller("sessionAttributeController") @RequestMapping("/springmvc") @SessionAttributes(value ={"username","password"},types={Integer.class}) public class SessionAttributeController { /** * 把数据存入 SessionAttribute * @param model * @return * Model 是 spring 提供的一个接口,该接口有一个实现类 ExtendedModelMap * 该类继承了 ModelMap,而 ModelMap 就是 LinkedHashMap 子类 */ @RequestMapping("/testPut") //存入数据 public String testPut(Model model){ model.addAttribute("username", "泰斯特"); model.addAttribute("password","123456"); model.addAttribute("age", 31); //跳转之前将数据保存到 username、password 和 age 中,因为注解@SessionAttribute 中有 这几个参数 return "success"; } @RequestMapping("/testGet") //获取数据 public String testGet(ModelMap model){ System.out.println(model.get("username")+";" +model.get("password")+";"+model.get("a ge")); return "success"; } @RequestMapping("/testClean") //清空数据 public String complete(SessionStatus sessionStatus){ sessionStatus.setComplete(); return "success"; } }
第二章
2.1 返回值
//方式一:空返回值,通过resquest和response设置 @RequestMapping("/testReturnVoid") public void testReturnVoid(HttpServletRequest request,HttpServletResponse response) throws Exception { //1、使用 request 转向页面,如下: request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request, response); //2、也可以通过 response 页面重定向: response.sendRedirect("testRetrunString") //3、也可以通过 response 指定响应结果,例如响应 json 数据: response.setCharacterEncoding("utf-8"); response.setContentType("application/json;charset=utf-8"); response.getWriter().write("json 串"); } //方式二:ModelAndView 是 SpringMVC 为我们提供的一个对象,该对象也可以用作控制器方法的返回值 @RequestMapping("/testReturnModelAndView") public ModelAndView testReturnModelAndView() { ModelAndView mv = new ModelAndView(); mv.addObject("username", "张三"); //将属性添加到request域中 mv.setViewName("success"); //设置转发视图页面 }
//获取 <body> 执行成功! ${requestScope.username} </body>
2.2 转发和重定向
//转发 @RequestMapping("/testForward") public String testForward() { System.out.println("AccountController 的 testForward 方法执行了。。。。"); return "forward:/WEB-INF/pages/success.jsp"; } //如果用了 formward:则路径必须写成实际视图 url,不能写逻辑视图 //它相当于“request.getRequestDispatcher("url").forward(request,response)”。 //重定向 @RequestMapping("/testRedirect") public String testRedirect() { System.out.println("AccountController 的 testRedirect 方法执行了。。。。"); return "redirect:testReturnModelAndView"; } //它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到 jsp 页面,则 jsp 页面不 能写在 WEB-INF 目录中,否则无法找到
2.3 ResponseBody响应json数据
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $("#testJson").click(function(){ $.ajax({ type:"post", url:"${pageContext.request.contextPath}/testResponseJson", contentType:"application/json;charset=utf-8", data:'{"id":1,"name":"test","money":999.0}', dataType:"json", success:function(data){ alert(data); } }); }); }) </script> <!-- 测试异步请求 --> <input type="button" value=" 测试 ajax请求 json和响应 json" id="testJson"/>
@Controller("jsonController") public class JsonController { /** * 测试响应 json 数据 */ @RequestMapping("/testResponseJson") public @ResponseBody Account testResponseJson(@RequestBody Account account) { System.out.println("异步请求:"+account); return account; } }
2.4 SpringMVC实现文件上传
- 前提
A form 表单的 enctype 取值必须是:multipart/form-data (默认值是:application/x-www-form-urlencoded) enctype:是表单请求正文的类型 B method 属性取值必须是 Post C 提供一个文件选择域<input type=”file” /> 因为 当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。 enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是: key=value&key=value&key=value 当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成: 每一部分都是 MIME 类型描述的正文
- 导入相关依赖jar包(io,fileupload相关的jar包)
- 编写jsp页面
- 编写控制器
- 配置文件解析器
<form action="/fileUpload" method="post" enctype="multipart/form-data"> 名称:<input type="text" name="picname"/><br/> 图片:<input type="file" name="uploadFile"/><br/> <input type="submit" value=" 上传 "/> </form>
@Controller("fileUploadController") public class FileUploadController { /** * 文件上传 */ @RequestMapping("/fileUpload") public String testResponseJson(String picname,MultipartFile uploadFile,HttpServletRequest request) throws Exception{ //定义文件名 String fileName = ""; //1.获取原始文件名 String uploadFileName = uploadFile.getOriginalFilename(); //2.截取文件扩展名 String extendName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1, uploadFileName.length()); //3.把文件加上随机数,防止文件重复 String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase(); //4.判断是否输入了文件名 if(!StringUtils.isEmpty(picname)) { fileName = uuid+"_"+picname+"."+extendName; }else { fileName = uuid+"_"+uploadFileName; } System.out.println(fileName); //2.获取文件路径 ServletContext context = request.getServletContext(); String basePath = context.getRealPath("/uploads"); //3.解决同一文件夹中文件过多问题 String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); //4.判断路径是否存在 File file = new File(basePath+"/"+datePath); if(!file.exists()) { file.mkdirs(); } //5.使用 MulitpartFile 接口中方法,把上传的文件写到指定位置 uploadFile.transferTo(new File(file,fileName)); return "success"; } }
<!-- 配置文件上传解析器 --> <!-- id 的值是固定的--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置上传文件的最大尺寸为 5MB --> <property name="maxUploadSize"> <value>5242880</value> </property> </bean> 注意: 文件上传的解析器 id是固定的,不能起别的名称,否则无法实现请求参数的绑定。(不光是文件,其他 字段也将无法绑定)
2.5 springmvc跨服务器的文件上传
- 不同的服务器
- 应用服务器:负责部署我们的应用
- 数据库服务器:运行我们的数据库
- 缓存和消息服务器:负责处理大并发访问的缓存和消息
- 文件服务器:负责存储用户上传文件的服务器
- 步骤
- 准备两个 tomcat 服务器,并创建一个用于存放图片的 web 工程
- 拷贝jar包(添加依赖)
- 编写控制器实现上传图片
- 编写jsp页面
- 配置解析器
@Controller("fileUploadController2") public class FileUploadController2 { public static final String FILESERVERURL = "http://localhost:9090/day06_spring_image/uploads/"; /** * 文件上传,保存文件到不同服务器 */ @RequestMapping("/fileUpload2") public String testResponseJson(String picname,MultipartFile uploadFile) throws Exception{ //定义文件名 String fileName = ""; //1.获取原始文件名 String uploadFileName = uploadFile.getOriginalFilename(); //2.截取文件扩展名 String extendName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1, uploadFileName.length()); //3.把文件加上随机数,防止文件重复 String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase(); //4.判断是否输入了文件名 if(!StringUtils.isEmpty(picname)) { fileName = uuid+"_"+picname+"."+extendName; }else { fileName = uuid+"_"+uploadFileName; } System.out.println(fileName); //5.创建 sun 公司提供的 jersey 包中的 Client 对象 Client client = Client.create(); //6.指定上传文件的地址,该地址是 web 路径 WebResource resource = client.resource(FILESERVERURL+fileName); //7.实现上传 String result = resource.put(String.class,uploadFile.getBytes()); System.out.println(result); return "success"; } }
<form action="fileUpload2" method="post" enctype="multipart/form-data"> 名称:<input type="text" name="picname"/><br/> 图片:<input type="file" name="uploadFile"/><br/> <input type="submit" value="上传"/> </form>
<!-- 配置文件上传解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设置上传文件的最大尺寸为 5MB --> <property name="maxUploadSize"> <value>5242880</value> </property> </bean>
3.6 SpringMVC中的异常处理
- 编写异常类和错误页面
- 自定义异常处理器
- 配置异常处理器
public class CustomException extends Exception { private String message; public CustomException(String message) { this.message = message; } public String getMessage() { return message; } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title> 执行失败 </title> </head> <body> 执行失败! ${message } </body> </html>
public class CustomExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ex.printStackTrace(); CustomException customException = null; //如果抛出的是系统自定义异常则直接转换 if(ex instanceof CustomException){ customException = (CustomException)ex; }else{ //如果抛出的不是系统自定义异常则重新构造一个系统错误异常。 customException = new CustomException("系统错误,请与系统管理 员联系!"); } ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("message", customException.getMessage()); modelAndView.setViewName("error"); return modelAndView; } }
<bean id="handlerExceptionResolver" class="com.itheima.exception.CustomExceptionResolver"/>
3.7 SpringMVC中的拦截器
- 编写一个普通类实现HandlerInterceptor接口
- 配置拦截器
public class HandlerInterceptorDemo1 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception { System.out.println("preHandle 拦截器拦截了"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception { System.out.println("postHandle 方法执行了"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception { System.out.println("afterCompletion 方法执行了"); } }
<!-- 配置拦截器的作用范围 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /><!-- 用于指定对拦截的 url --> <mvc:exclude-mapping path=""/><!-- 用于指定排除的 url--> <bean id="handlerInterceptorDemo1" class="com.itheima.web.interceptor.HandlerInterceptorDemo1"></bean> </mvc:interceptor> </mvc:interceptors>
第三章
3.1 SSM整合
- 创建数据库和表结构
- 创建Maven工程
- 导入坐标引入依赖
- 编写实体类
- 编写业务层接口
- 编写持久层接口
- 保证Spring框架在web工程上独立运行
- 编写spring配置文件并导入约束
- 使用注解配置业务层和持久层
- 测试spring能否独立运行
- 保证SpringMVC在web工程独立运行
- 在web.xml中配置核心控制器(DispatcherServlet)
- 编写SpringMVC的配置文件
- 编写Controller和jsp页面
- 整合Spring和SpringMVC
- 配置监听器实现启动服务创建容器
- 保证MyBatis框架在web工程中独立运行
- 编写AccountDao映射配置文件
- 编写SqlMapConfig配置文件
- 测试运行结果
- 整合Spring和Mybatis
- Spring接管MyBatis的Session工厂
- 配置自动扫描所有Mapper接口和文件
- 配置Spring的事物
- 测试整合结果
- 测试SSM整合结果
- 编写测试jsp
- 修改控制器的方法
- 测试运行结果
create database ssm; create table account( id int primary key auto_increment, name varchar(100), money double(7,2), );
@Service("accountService") public class AccountServiceImpl implements AccountService{ @Autowired private AccountDao accountDao; public List<Account> findAll() { System.out.println("业务层:查询所有账户..."); return accountDao.findAll(); } public void saveAccount(Account account) { System.out.println("业务层:保存帐户..."); accountDao.saveAccount(account); } }
@Repository public interface AccountDao { // 查询所有账户 @Select("select * from account") public List<Account> findAll(); // 保存帐户信息 @Insert("insert into account (name,money) values (#{name},#{money})") public void saveAccount(Account account); }
//测试spring public class Test01Spring { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); IAccountService as = ac.getBean("accountService",IAccountService.class); as.findAllAccount(); } }
//配置web.xml <web-app> <display-name>Archetype Created Web Application</display-name> <!--配置Spring的监听器,默认只加载WEB-INF目录下的applicationContext.xml配置文件--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--设置配置文件的路径--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <context-param> <param-name/> <param-value/> </context-param> <!--配置前端控制器--> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--加载springmvc.xml配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!--启动服务器,创建该servlet--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!--解决中文乱码的过滤器--> <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-app>
//配置SpringMVC的配置文件 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--开启注解扫描,只扫描Controller注解--> <context:component-scan base-package="cn.itcast"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <!--配置的视图解析器对象--> <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean> <!--过滤静态资源--> <mvc:resources location="/css/" mapping="/css/**" /> <mvc:resources location="/images/" mapping="/images/**" /> <mvc:resources location="/js/" mapping="/js/**" /> <!--开启SpringMVC注解的支持--> <mvc:annotation-driven/> </beans>
//编写jsp页面 <body> <a href="account/findAll">测试查询</a> <h3>测试包</h3> <form action="account/save" method="post"> 姓名:<input type="text" name="name" /><br/> 金额:<input type="text" name="money" /><br/> <input type="submit" value="保存"/><br/> </form> </body>
//控制器 @Controller @RequestMapping("/account") public class AccountController { @Autowired private AccountService accountService; @RequestMapping("/findAll") public String findAll(Model model){ System.out.println("表现层:查询所有账户..."); // 调用service的方法 List<Account> list = accountService.findAll(); model.addAttribute("list",list); return "list"; } /** * 保存 * @return */ @RequestMapping("/save") public void save(Account account, HttpServletRequest request, HttpServletResponse response) throws IOException { accountService.saveAccount(account); response.sendRedirect(request.getContextPath()+"/account/findAll"); return; } }
来源:https://www.cnblogs.com/liujiashun/p/12215154.html