三層結構介紹
表現層:
* 也就是我們常說的web 層。它負責接收客戶端請求,向客戶端響應結果,通常客戶端使用http 協議請求web 層,web 需要接收 http 請求,完成 http 響應。
* 表現層包括展示層和控制層:控制層負責接收請求,展示層負責結果的展示。
* 表現層依賴業務層,接收到客戶端請求一般會調用業務層進行業務處理,並將處理結果響應給客戶端。
* 表現層的設計一般都使用 MVC 模型。(MVC 是表現層的設計模型,和其他層沒有關系)
業務層:
* 也就是我們常說的 service 層。它負責業務邏輯處理,和我們開發項目的需求息息相關。web 層依賴業務層,但是業務層不依賴 web 層。
* 業務層在業務處理時可能會依賴持久層,如果要對數據持久化需要保證事務一致性。(也就是我們說的, 事務應該放到業務層來控制)
持久層:
* 也就是我們是常說的 dao 層。負責數據持久化,包括數據層即數據庫和數據訪問層,數據庫是對數據進行持久化的載體,數據訪問層是業務層和持久層交互的接口,業務層需要通過數據訪問層將數據持久化到數據庫中。通俗的講,持久層就是和數據庫交互,對數據庫表進行曾刪改查的。
SpringMvc是什么?
SpringMVC 是一種基於 Java 的實現 MVC 設計模型的請求驅動類型的輕量級 Web 框架,屬於 SpringFrameWork 的后續產品,已經融合在 Spring Web Flow 里面。Spring 框架提供了構建 Web 應用程序的全功能 MVC 模塊。使用 Spring 可插入的 MVC 架構,從而在使用 Spring 進行 WEB 開發時,可以選擇使用 Spring 的 Spring MVC 框架或集成其他 MVC 開發框架,如 Struts1(現在一般不用),Struts2 等
SpringMvc整體結構
開發環境:
本案例使用開發環境:
Jdk:jdk1.8
IDE:Oxygen
Tomcat:apache-tomcat-8.5.x
Springmvc:5.0.7
編寫簡單的springmvc程序:
package com.kkb.springmvc.controller; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.kkb.springmvc.po.Item; /*** * 處理器的開發方式有多種,比如實現HttpRequestHandler接口、Controller接口的方式,還有注解的方式 * 企業中使用的一般來講都是注解的方式 注解的方式,主要有兩個注意事項: * 類上加上@Controller注解(必須是Controller,可以通過源碼找到答案) 類上或者方法上面要加上@RequestMapping注解(必須的) * * @author think * */ @Controller public class ItemController { // @RequestMapping此時填寫的是url // ModelAndView:model表示的是數據模型,view就是最終要展示給用戶的視圖 @RequestMapping("queryItem") public ModelAndView queryItem() { // 查詢數據庫,用靜態數據模擬 List<Item> itemList = new ArrayList<>(); // 商品列表 Item item_1 = new Item(); item_1.setName("聯想筆記本_3"); item_1.setPrice(6000f); item_1.setDetail("ThinkPad T430 聯想筆記本電腦!"); Item item_2 = new Item(); item_2.setName("蘋果手機"); item_2.setPrice(5000f); item_2.setDetail("iphone6蘋果手機!"); itemList.add(item_1); itemList.add(item_2); ModelAndView mvAndView = new ModelAndView(); // 設置數據模型,相當於request的setAttribute方法,實質上,底層確實也是轉成了request(暫時這樣理解) // 先將k/v數據放入map中,最終根據視圖對象不同,再進行后續處理 mvAndView.addObject("itemList", itemList); // 設置視圖(邏輯路徑) mvAndView.setViewName("item/item-list"); // mvAndView.setViewName("/WEB-INF/jsp/item/item-list.jsp"); return mvAndView; } }
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 處理器類的掃描 --> <context:component-scan base-package="com.kkb.springmvc.controller" /> <!--注解映射器 @Controller和@RequestMapping組合這種方式的注解映射的解析 --> <!-- <bean --> <!-- class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> --> <!--注解適配器 --> <!-- <bean --> <!-- class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" /> --> <!-- 配置注解的適配器和映射器,同時還注入了很多其他的bean --> <mvc:annotation-driven/> <!-- 顯式的配置視圖解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <!-- 學習前置條件 --> <!-- 問題1:web.xml中servelet、filter、listener、context-param加載順序 --> <!-- 問題2:load-on-startup標簽的作用,影響了servlet對象創建的時機 --> <!-- 問題3:url-pattern標簽的配置方式有四種:/dispatcherServlet、 /servlet/* 、*.do 、/ ,以上四種配置,加載順序是如何的--> <!-- 問題4:url-pattern標簽的配置為/*報錯,原因是它攔截了JSP請求,但是又不能處理JSP請求。為什么配置/就不攔截JSP請求,而配置/*,就會攔截JSP請求--> <!-- 問題5:配置了springmvc去讀取spring配置文件之后,就產生了spring父子容器的問題 --> <!-- 配置前端控制器 --> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 設置spring配置文件路徑 --> <!-- 如果不設置初始化參數,那么DispatcherServlet會讀取默認路徑下的配置文件 --> <!-- 默認配置文件路徑:/WEB-INF/springmvc-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 指定初始化時機,設置為2,表示Tomcat啟動時,DispatcherServlet會跟隨着初始化 --> <!-- 如果不指定初始化時機,DispatcherServlet就會在第一次被請求的時候,才會初始化,而且只會被初始化一次 --> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- URL-PATTERN的設置 --> <!-- 不要配置為/*,否則報錯 --> <!-- 通俗解釋:/*,會攔截整個項目中的資源訪問,包含JSP和靜態資源的訪問,對於靜態資源的訪問springMVC提供了默認的Handler處理器 --> <!-- 但是對於JSP來講,springmvc沒有提供默認的處理器,我們也沒有手動編寫對於的處理器,此時按照springmvc的處理流程分析得知,它短路了 --> <url-pattern>/</url-pattern> </servlet-mapping> <!-- <servlet> --> <!-- <servlet-name>sss</servlet-name> --> <!-- <servlet-class>sss</servlet-class> --> <!-- </servlet> --> <!-- <servlet-mapping> --> <!-- <servlet-name>sss</servlet-name> --> <!-- <url-pattern>/sss</url-pattern> --> <!-- </servlet-mapping> --> </web-app>
SSM框架的整合
配置版:
1.添加依賴 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.13.RELEASE</version> </dependency> 2.創建Student實體類 package cn.tina; public class Student { private int stuNo; private String name; public int getStuNo() { return stuNo; } public void setStuNo(int stuNo) { this.stuNo = stuNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 3.編寫spring核心配置文件applicationContext.xml <?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <bean id="student" class="cn.tina.Student"> <property name="name" value="張三"/> <property name="stuNo" value="1001"/> </bean> </beans> 4.編寫測試類 public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()+"---"+student.getStuNo()); }
注解版:
//添加依賴 <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.7</version> </dependency> <dependency> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>com.hynnet</groupId> <artifactId>oracle-driver-ojdbc6</artifactId> <version>12.1.0.1</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.6</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.1.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.1.9.RELEASE</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.0-alpha-1</version> <!-- 打包的時候忽略,因為tomcat中有,重復的包會沖突--> <scope>provided</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> </dependencies> //編寫實體類 package cn.entity; public class Grade { private int gradeId; private String gradeName; @Override public String toString() { return "Grade{" + "gradeId=" + gradeId + ", gradeName='" + gradeName + '\'' + '}'; } public int getGradeId() { return gradeId; } public void setGradeId(int gradeId) { this.gradeId = gradeId; } public String getGradeName() { return gradeName; } public void setGradeName(String gradeName) { this.gradeName = gradeName; } } //編寫Mapper package cn.dao; import cn.entity.Grade; import java.util.List; public interface GradeMapper { public List<Grade> getListGrade(); public int addGrade(Grade grade); } //編寫Mapper.xml 注意放入resource下同名文件夾 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- SQL映射文件 --> <mapper namespace="cn.dao.GradeMapper"> <select id="getListGrade" resultType="Grade"> select * from grade </select> <insert id="addGrade" parameterType="Grade"> insert into grade(gradeId,gradeName)values(#{gradeId},#{gradeName}) </insert> </mapper> //編寫Service package cn.service; import cn.entity.Grade; import java.util.List; public interface GradeService { public List<Grade> getListGrade(); public int addGrade(Grade grade); } 編寫實現類: package cn.service.impl; import cn.dao.GradeMapper; import cn.entity.Grade; import cn.service.GradeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service//默認bean的名稱與類名同名,只是首字母改為小寫 public class GradeServiceImpl implements GradeService { @Autowired//可以從spring容器中取出gradeMapper組件 GradeMapper gradeMapper; @Override public List<Grade> getListGrade() { return gradeMapper.getListGrade(); } @Transactional //添加事務注解 public int addGrade(Grade grade) { int cn = gradeMapper.addGrade(grade); // int i=1/0; //這個錯誤不能去捕獲 讓spring容器處理 會回滾數據 return cn; } } //編寫Spring配置類 package cn.config; import org.apache.commons.dbcp.BasicDataSource; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration @ComponentScan(value = "cn") @EnableTransactionManagement//開啟注解式事務 @EnableAspectJAutoProxy //開啟注解式aop public class SpringConfig { @Bean//在spring中注入一個數據源 public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); //mysql--連接 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setPassword("root"); dataSource.setUsername("root"); dataSource.setUrl("jdbc:mysql://localhost:3306/myschool"); /* dataSource.setUsername("system"); dataSource.setPassword("root"); dataSource.setDriverClassName("oracle.jdbc.OracleDriver"); dataSource.setUrl("jdbc:oracle:thin:@localhost:1521:orcl");*/ return dataSource; } @Bean //設置session工廠 public SqlSessionFactoryBean sqlSessionFactory( DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); sqlSessionFactoryBean.setTypeAliasesPackage("cn.entity"); //如果命名規范,且在同一個包中,可省略 // ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); // try { // sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:cn/dao/*Dao.xml")); // } catch (IOException e) { // e.printStackTrace(); // } return sqlSessionFactoryBean; } @Bean//掃描mapper 為它生成mapper的實現類 public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("cn.dao"); return mapperScannerConfigurer; } //配置事務管理器 @Bean public PlatformTransactionManager transactionManager(DataSource dataSource ){ return new DataSourceTransactionManager(dataSource); } } //先編寫main方法,測試spring和myabtis是否整合完成 public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); GradeService gradeService = (GradeService) context.getBean("gradeServiceImpl"); Grade grade=new Grade(); grade.setGradeId(5); grade.setGradeName("444"); int cn =gradeService.addGrade(grade); System.out.println(cn+"---------------"); } //編寫Controller package cn.controller; import cn.entity.Grade; import cn.service.GradeService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.Resource; import java.util.List; @Controller public class GradeController { @Resource GradeService gradeService; @RequestMapping("/") public String toIndex(){ return "redirect:/index"; } @RequestMapping("/add") public String add(Grade grade, Model model){ int cn =gradeService.addGrade(grade); model.addAttribute("msg","新增成功"); return "forward:/index"; } @RequestMapping("/index") public String index(Model model){ List<Grade> list= gradeService.getListGrade(); model.addAttribute("list",list); return "index"; } } //編寫全局異常處理類 //這個注解可以對全局異常,或者數據類型轉換 @ControllerAdvice public class MyAdvice { @ExceptionHandler public String handlerException(Exception e, HttpServletRequest request) { request.setAttribute("msg", "異常:" + e.getMessage()); return "error"; } /* @InitBinder //使用配置轉換器方式 public void web(WebDataBinder binder) { binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); }*/ } //編寫前台到后台的日期轉換器 public class StringFormatByDate implements Converter<String, Date> { @Override public Date convert(String s) { SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); try { return sf.parse(s); } catch (ParseException e) { e.printStackTrace(); return null; } } } //配置攔截器 public class MyInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { System.out.println("進入了攔截。。。。。"); return true; } } //編寫MVC配置類 @Configuration @EnableWebMvc //相當於開啟注解方式 @ComponentScan(value = "cn.controller") public class MvcConfig extends WebMvcConfigurerAdapter { @Override //視圖解析器 注意:views文件夾在resource下 public void configureViewResolvers(ViewResolverRegistry registry) { registry.jsp("/WEB-INF/classes/views/", ".jsp"); } @Override//不能直接使用add.jsp 配置一個跳轉 public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/toAdd").setViewName("add"); } @Override //靜態資源映射 注意:static文件夾在resources下 public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**") .addResourceLocations("classpath:/static/"); } @Override //json前台到后台的問題:中文編碼和日期問題 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); fastJsonHttpMessageConverter.setCharset(Charset.forName("utf-8")); fastJsonHttpMessageConverter.setFeatures(SerializerFeature.WriteDateUseDateFormat); converters.add(fastJsonHttpMessageConverter); } @Override //注冊 :前台到后台的日期問題 public void addFormatters(FormatterRegistry registry) { registry.addConverter(new StringFormatByDate()); } @Override //配置攔截器 public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()); } } //取代在web.xml配置中的啟動spring和mvc public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override//相當於在以前web.xml中配置的讀取applicationContext.xml protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class};//用於Spring的配置 } @Override//相當於在以前web.xml中配置的讀取springmvc-servlet.xml protected Class<?>[] getServletConfigClasses() { return new Class[]{MvcConfig.class};//專門用於MVC的配置 } @Override protected String[] getServletMappings() { // /處理請求,不攔截jsp /* 會攔截jsp return new String[]{"/"}; } /* 添加過濾器*/ @Override protected Filter[] getServletFilters() { CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setForceEncoding(true); return new Filter[]{characterEncodingFilter}; } }