1.SpringMVC技术
1.1 技术介绍
一个MVC框架,在web模型中,MVC是一种很流行的框架,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,是为了简化开发,减少出错。
1.2 技术注意点
1.2.1 @RequestParam注解
请求参数名和列对不上时,可以使用required="false"来选择可以不用传参,defaultValue来默认请求参数。
public String add(@RequestParam(value="id" required=false)Integer idxxxa, defaultValue="1"){
...
}
1.2.2 设置请求和响应编码格式
修改web.xml
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.2.3 静态资源放行
修改spring-mvc.xml
<mvc:resources mapping="/img/**" location="/img/" />
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/html/**" location="/html/" />
1.2.4 全局更改编码
修改tomcat的server.xml
<Connector URIEncoding="UTF-8" connectionTimeout="20000", port="8080" protocol="HTTP/1.1" ......>
1.2.5 @ResponseBody注解
加上这个注解后,是无法返回jsp页面,所以在springmvc中要根据@RestController
@RequestMapping("/getStudent")
@ResponseBody
public String getStudentInfo(@RequestParam(value = "id", required = false) Long id,ModelMap model) {
List<Student> student = studentService.getStudentById(id);
System.out.println(student);
model.addAttribute("student", student.get(0));
return "student";
}
1.3 技术具体demo文件路径
链接:https://pan.baidu.com/s/1j2-VIv-A5jNgX2WJiQaaAw
提取码:hm00
1.4 demo的UML图
1.5 demo的技术代码实现
1.5.1 pom的编写
<!--统一jar包-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.vision>5.0.2.RELEASE</spring.vision>
<shiro.version>1.2.3</shiro.version>
<junit.version>4.12</junit.version>
<mysql.version>5.1.38</mysql.version>
<mybatis.ehcache.version>1.1.0</mybatis.ehcache.version>
<log4j.version>1.2.17</log4j.version>
<slf4j.version>1.7.5</slf4j.version>
<slf4j.log4j.version>1.7.12</slf4j.log4j.version>
<mybatis.generator.version>1.3.2</mybatis.generator.version>
<cglib.version>3.1</cglib.version>
<asm.version>3.3.1</asm.version>
<pagehelper.version>5.1.8</pagehelper.version>
<mybatis.spring.version>1.3.2</mybatis.spring.version>
<aspectjweaver.version>1.9.2</aspectjweaver.version>
<c3p0.version>0.9.5.2</c3p0.version>
</properties>
<dependencies>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<!--mybatis框架-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- JUnit单元测试工具 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<!-- 表示开发的时候引入,发布的时候不会加载此包 -->
<scope>test</scope>
</dependency>
<!--mysql连接池jar包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--缓存-->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>${mybatis.ehcache.version}</version>
</dependency>
<!--打印日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.log4j.version}</version>
</dependency>
<!--自动生成bean-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis.generator.version}</version>
</dependency>
<!--toString与重载方法过滤-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>${cglib.version}</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>${asm.version}</version>
</dependency>
<!--分页-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<!--spring框架核心库-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.vision}</version>
</dependency>
<!-- spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.vision}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.vision}</version>
</dependency>
<!--Spring java数据库访问包,在本例中主要用于提供数据源 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.vision}</version>
</dependency>
<!--Spring Web-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.vision}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.vision}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.vision}</version>
</dependency>
<!--spring和mybatis整合-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<!-- aspectjweaver 切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectjweaver.version}</version>
</dependency>
<!--最新版c3p0连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
</dependencies>
1.5.2 数据源的配置 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/stus?useUnicode=true&characterEncoding=utf8&useSSL=false
jdbc.username=root
jdbc.password=123
#最大连接数
maxPoolSize=100
#最小连接数
minPoolSize=20
# 关闭连接后不自动commit
autoCommitOnClose=false
# 获取连接超时时间
checkoutTimeout=10000
# 初始化连接
initialSize=30
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
#连接数
acquireIncrement=30
1.5.3 日志的配置 log4j.properties
#---- global logging configuration
#---- level: FATAL,ERROR,WARN,INFO,DEBUG
#---- appender: console, file, mail
### set log levels ###
log4j.rootLogger = DEBUG,console
### 输出到控制台 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d{yyyy-MM-dd HH\:mm\:ss} %5p %c{1}:%L - %m%n
### 输出到日志文件 ###
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File = ${webapp.root}/WEB-INF/logs/platform.log
log4j.appender.file.DatePattern=_yyyyMMdd'.log'
#log4j.appender.file.Append = true
#log4j.appender.file.Threshold = INFO
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern =%-d{yyyy-MM-dd HH\:mm\:ss} [ %t\:%r ] - [ %p ] %m%n
### 打印SQL ###
#log4j.logger.com.ibatis=DEBUG
#log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
#log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
#log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
#log4j.logger.java.sql.ResultSet=DEBUG
1.5.4 web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 加载Spring容器配置 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 设置Spring容器加载所有的配置文件的路径 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,classpath:spring-mvc.xml</param-value>
</context-param>
<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 启动加载一次 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<!-- 默认匹配所有的请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 防止Spring内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<!-- 解决工程编码过滤器 -->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
1.5.5 springmvc.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
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 ">
<!-- 自动扫描controller包下所有的类,成为spring mvc 的控制器-->
<context:component-scan base-package="org.hikktn.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter>
</context:component-scan>
<!--视图解析器-->
<!--定义JSP文件的位置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
<property name="order" value="0"></property>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>
<property name="prefix" value="/html/" />
<property name="order" value="10"></property>
<property name="suffix" value=".html" />
</bean>
<!-- 视图解析器:通用视图名来解析视图(Excel) -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="100"></property>
</bean>
<context:annotation-config/>
<!-- 开启注解( 用于将对象转换为 JSON) -->
<mvc:annotation-driven/>
<!--处理静态资源-->
<mvc:default-servlet-handler></mvc:default-servlet-handler>
<!--
配置静态资源,直接映射到对应的文件夹,不被DispatcherServlet处理,3.04新增功能,需要重新设置spring-mvc-3.0.xsd
-->
<mvc:resources mapping="/img/**" location="/img/" />
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/html/**" location="/html/" />
<!-- 定义文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8">
<!-- 设定文件上传的最大值为100MB,100*1024*1024 -->
<property name="maxUploadSize">
<value>104857600</value>
</property>
<property name="maxInMemorySize">
<value>40960</value>
</property>
</bean>
</beans>
1.5.6 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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--引入属性文件,在配置中占位使用 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置C3P0数据源-->
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!--连接数据库的基本信息-->
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="driverClass" value="${jdbc.driver}" />
<!--连接池的相应配置-->
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<property name="minPoolSize" value="${minPoolSize}"></property>
<property name="initialPoolSize" value="${initialSize}"></property>
<property name="acquireIncrement" value="${acquireIncrement}"></property>
<property name="autoCommitOnClose" value="${autoCommitOnClose}"></property>
</bean>
<!--配置mybatis的工厂-->
<bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据源-->
<property name="dataSource" ref="ds"></property>
<!-- 配置MyBaties全局配置文件:mybatis-config.xml -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--类的别名的包-->
<property name="typeAliasesPackage" value="org.hikktn.model"></property>
<!-- 扫描sql配置文件:mapper需要的xml文件 -->
<property name="mapperLocations" value="classpath*:mapper/*.xml" />
</bean>
<!--spring和mybatis整合 (自动扫描映射接口)-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定ioc容器中的mybatis工厂的bean的名字-->
<property name="sqlSessionFactoryBeanName" value="sessionFactoryBean"></property>
<!--mapper所在的包-->
<property name="basePackage" value="org.hikktn.dao"></property>
</bean>
<!--声明式事务管理-->
<!--定义事物管理器,由spring管理事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"></property>
</bean>
<!--支持注解驱动的事务管理,指定事务管理器 -->
<!--事务属性-->
<tx:advice id="advice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" isolation="READ_COMMITTED" propagation="REQUIRED"/>
<tx:method name="insert*" isolation="SERIALIZABLE" propagation="REQUIRED"></tx:method>
</tx:attributes>
</tx:advice>
<!--配置事务(拦截service)-->
<aop:config>
<!--切入点表达式-->
<aop:pointcut id="pc" expression="execution(* org.hikktn.service.*.*(..))"></aop:pointcut>
<!--关联切入点表达式和事务属性-->
<aop:advisor advice-ref="advice" pointcut-ref="pc"></aop:advisor>
</aop:config>
<!--使事务注解起作用-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
<!--只扫描controller的包以外的包-->
<context:component-scan base-package="org.hikktn">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
</context:component-scan>
<!--aspectj支持自动代理实现AOP功能-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
<!-- 拦截器方式配置事物(这里可以不写,只是方便在advice的事务方便增加相应的事务配置) -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="append*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="modify*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="repair" propagation="REQUIRED" />
<tx:method name="delAndRepair" propagation="REQUIRED" />
<tx:method name="get*" propagation="SUPPORTS" />
<tx:method name="find*" propagation="SUPPORTS" />
<tx:method name="load*" propagation="SUPPORTS" />
<tx:method name="search*" propagation="SUPPORTS" />
<tx:method name="datagrid*" propagation="SUPPORTS" />
<tx:method name="*" propagation="SUPPORTS" />
</tx:attributes>
</tx:advice>
</beans>
1.5.7 model的准备
package org.hikktn.model;
public class Student {
/**
* 主键
*/
private Long id;
/**
* 名称
*/
private String name;
/**
* 年齡
*/
private Long age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getAge() {
return age;
}
public void setAge(Long age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
}
}
1.5.8 dao的编写
@Repository
public interface StudentDao {
List<Student> getStudentById(@Param("id")Long id);
}
1.5.9 service的编写
public interface StudentService {
List<Student> getStudentById(Long id);
}
1.5.10 service实现类的编写
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentDao studentDao;
public List<Student> getStudentById(Long id) {
List<Student> student = studentDao.getStudentById(id);
return student;
}
}
1.5.11 Controller的编写
@Controller
public class StudentController {
@Autowired
private StudentService studentService;
@RequestMapping(value = "/hello")
public String hello(ModelMap model) {
model.addAttribute("message", "Spring 3 MVC Hello World");
return "index";
}
@RequestMapping("/getStudent")
public String getStudentInfo(@RequestParam(value = "id", required = false) Long id,ModelMap model) {
List<Student> student = studentService.getStudentById(id);
System.out.println(student);
model.addAttribute("student", student.get(0));
return "student";
}
}
1.5.12 启动访问路径
http://localhost:8080/getStudent?id=1
1.5.13 jsp的编写
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<span>Hello World!</span>
<p>message:${message}</p>
</body>
</html>
student.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<p>学生信息:</p>
<p>学生姓名:${student.name}</p>
<p>学生年龄:${student.age}</p>
</body>
</html>
1.6 对应博客地址
1.7 环境准备
1.7.1 在idea上准备tomcat
https://blog.csdn.net/wsjzzcbq/article/details/89463304
1.7.2 idea上配置webapp
https://blog.csdn.net/qq_44575680/article/details/89449581
1.7.3 idea上移除或加入jar包
解释:左侧的available elements里面,如果出现jar包,则直接手动拖动lib目录下,并移除lib目录下报红的jar包,报红的jar包代表不存在。这里主要是当你的jar包出现冲突,某个类找不到的时候,你需要更改pom,但是maven依赖成功了,问题还是没有解决,这时你就需要手动排除掉一些错误引入的jar包,保证正确的jar包引入。
1.7.4 配置详解
1.7.4.1 数据库的数据源配置解释
本次使用的C3P0作为练习,即在applicationContext.xml中配置
<!--引入属性文件,在配置中占位使用 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--配置C3P0数据源-->
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!--连接数据库的基本信息-->
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="driverClass" value="${jdbc.driver}" />
<!--连接池的相应配置-->
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<property name="minPoolSize" value="${minPoolSize}"></property>
<property name="initialPoolSize" value="${initialSize}"></property>
<property name="acquireIncrement" value="${acquireIncrement}"></property>
<property name="autoCommitOnClose" value="${autoCommitOnClose}"></property>
</bean>
这样就能连接数据库。
1.7.4.2 applicationContext上下文配置
下面的模板,只需要更改红框起来的地方,其他可以不用修改。