SSM整合开发(三)—Web层
首先感谢慕课网的老师,讲的真的很棒,学习很多书本上学不到的实用知识。
学习课程的地址:https://www.imooc.com/learn/630
老师的GitHub地址:https://github.com/geekyijun/seckill
概要
主要介绍前端交互设计、Restful:url满足Restful设计规范、Spring MVC、bootstrap+jquery这四个方面的开发。
关于Restful
什么是Restful?它就是一种优雅的URI表述方式,用来设计我们资源的访问URL。通过这个URL的设计,我们就可以很自然的感知到这个URL代表的是哪种业务场景或者什么样的数据或资源。为什么要设计URL?对于初学者和不严格的系统来说,URL基本上不用理会。基本上不会根据业务需求从系统角度出发去设计URL。基于Restful设计的URL,对于我们接口的使用者、前端、web系统或者搜索引擎甚至是我们的用户,都是非常友好的。详细内容这里不再赘述。
关于MVC运行流程
使用SpringMVC始终是围绕Handler进行开发,Handler最终产生Model和View。
如图展示了MVC运行流程,这里稍微回顾一下,DispatcherServlet作为中央控制器的Servlet,拦截用户的所有请求。使用默认的DefaultAnnotationHandlerMapping,用来映射我们的URL——>Handler。使用默认的DefaultAnnotationHandlerAdapter进行Handler适配,能够衔接我们开发的controller部分,若有拦截器,也会绑定当流程当中。最终的产出是ModelAndView。InternalResourceViewResolver默认的jsp的view。将Model和xxx.jsp页面相结合返回给用户。
我们开发只要开发蓝色的Controller部分就可以了,其他部分可以使用默认注解的形式方便的进行开发。
RequestMapping注解映射技巧
1. 支持标准的URL。
2. 支持Ant风格URL(即?、*、**等字符)
3. 带{xxx}占位符URL,可以支持传入参数。
例如:/user/*/creation匹配/user/aaa/creation
/user/**/creation匹配/user/creation、/user/aaa/bbb/creation等
/user/{userId}匹配/user/123、user/abc等。
Web层
配置SpringMVC框架
web.xml
配置DispatcherServlet、Spring需要加载的一些文件写到contextConfigLocation中。
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <!--用maven创建的web-app需要修改servlet的版本为3.1--> <!--配置DispatcherServlet--> <servlet> <servlet-name>seckill-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置SpringMVC 需要配置的文件 spring-dao.xml,spring-service.xml,spring-web.xml Mybites -> spring -> springMvc --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-*.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>seckill-dispatcher</servlet-name> <!--默认匹配所有请求--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
spring-web.xml
在spring容器中进行web层相关bean(即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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--配置spring mvc--> <!--1,开启springmvc注解模式 a.自动注册DefaultAnnotationHandlerMapping,AnnotationMethodHandlerAdapter b.默认提供一系列的功能:数据绑定,数字和日期的format@NumberFormat,@DateTimeFormat c:xml,json的默认读写支持--> <mvc:annotation-driven/> <!--2.静态资源默认servlet配置--> <!-- 1).加入对静态资源处理:js,gif,png 2).允许使用 "/" 做整体映射 --> <mvc:default-servlet-handler/> <!--3:配置JSP 显示ViewResolver--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!--4:扫描web相关的controller--> <context:component-scan base-package="com.seu.web"/> </beans>
SeckillController.java
@Component @RequestMapping("/seckill")//url:模块/资源/{}/细分 public class SeckillController { @Autowired private SeckillService seckillService; @RequestMapping(value = "/list",method = RequestMethod.GET) public String list(Model model) { //list.jsp+mode=ModelAndView //获取列表页 List<Seckill> list=seckillService.getSeckillList(); model.addAttribute("list",list); return "list"; } @RequestMapping(value = "/{seckillId}/detail",method = RequestMethod.GET) public String detail(@PathVariable("seckillId") Long seckillId, Model model) { if (seckillId == null) { return "redirect:/seckill/list"; } Seckill seckill=seckillService.getById(seckillId); if (seckill==null) { return "forward:/seckill/list"; } model.addAttribute("seckill",seckill); return "detail"; } //ajax ,json暴露秒杀接口的方法 @RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod.GET, //返回HTTP的response的header,告诉浏览器数据的格式 produces = {"application/json;charset=UTF-8"}) @ResponseBody//返回json的数据 public SeckillResult<Exposer> exposer(@PathVariable("seckillId") Long seckillId) { SeckillResult<Exposer> result; try{ Exposer exposer=seckillService.exportSeckillUrl(seckillId); result=new SeckillResult<Exposer>(true,exposer); }catch (Exception e) { e.printStackTrace(); result=new SeckillResult<Exposer>(false,e.getMessage()); } return result; } @RequestMapping(value = "/{seckillId}/{md5}/execution", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) @ResponseBody public SeckillResult<SeckillExecution> execute(@PathVariable("seckillId") Long seckillId, @PathVariable("md5") String md5, //request中这个cookie不是必须的,验证逻辑放在方法体中执行 @CookieValue(value = "userPhone",required = false) Long userPhone) { if (userPhone==null) { return new SeckillResult<SeckillExecution>(false,"未注册"); } SeckillResult<SeckillExecution> result; try { SeckillExecution execution = seckillService.executeSeckill(seckillId, userPhone, md5); return new SeckillResult<SeckillExecution>(true, execution); }catch (RepeatKillException e1) { SeckillExecution execution=new SeckillExecution(seckillId, SeckillStatEnum.REPEAT_KILL); return new SeckillResult<SeckillExecution>(true,execution); }catch (SeckillCloseException e2) { SeckillExecution execution=new SeckillExecution(seckillId, SeckillStatEnum.END); return new SeckillResult<SeckillExecution>(true,execution); } catch (Exception e) { SeckillExecution execution=new SeckillExecution(seckillId, SeckillStatEnum.INNER_ERROR); return new SeckillResult<SeckillExecution>(true,execution); } } //获取系统时间 @RequestMapping(value = "/time/now",method = RequestMethod.GET) @ResponseBody public SeckillResult<Long> time() { Date now=new Date(); return new SeckillResult<Long>(true,now.getTime()); } }
下面包括暴露秒杀接口返回的数据写在dto包中,用于封装成json数据。
SeckillResult.java(省略getter、setter和构造函数)
//将所有的ajax请求返回类型,全部封装成json数据 public class SeckillResult<T> { //请求是否成功 private boolean success; private T data; private String error; }
前端代码,由于本人精力有限,暂时没考虑学习前端内容。所以这里就不贴出来了,可在GitHub上查看(https://github.com/geekyijun/seckill),不过通过这门课程学习到了Bootstrap前端框架的使用,提供一站式前端开发,需要的时候可以查询使用。