ZZJ_淘淘商城项目:day01(RESTful Web Service、SVN)
淘淘商城项目是很适合初级Java程序员练习的实战项目,本次复习是另一位张老师教授的课,内容上与之前入老师版taotao商城比较有些新东西加了进来。
因此有必要记录下那些直到现在还可供参考的技术亮点分享出来。课前资料等内容还需要测试完毕后再打包上传,保证按照视频学习能够获得最大的收获。
使用maven管理项目:parent工程集中定义子模块所继承的依赖版本号
JSP相关的依赖坐标和commons-io的依赖坐标视频中的写法与现在maven中央仓库不一致会报错
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.parent</groupId> <artifactId>itcast-parent</artifactId> <version>0.0.2-SNAPSHOT</version> <packaging>pom</packaging> <!-- 集中定义依赖版本号,参考了SpringBboot启动器的版本 --> <properties> <junit.version>4.12</junit.version> <slf4j.version>1.7.28</slf4j.version> <spring.version>4.3.25.RELEASE</spring.version> <mybatis.version>3.4.6</mybatis.version> <mybatis.spring.version>1.3.2</mybatis.spring.version> <mybatis.paginator.version>1.2.17</mybatis.paginator.version> <mapper.version>4.1.5</mapper.version> <pagehelper.version>5.1.10</pagehelper.version> <jsqlparser.version>2.0</jsqlparser.version> <mysql.version>5.1.47</mysql.version> <druid.version>1.1.15</druid.version> <jackson.version>2.9.9.3</jackson.version> <jstl.version>1.2</jstl.version> <servlet-api.version>3.1.0</servlet-api.version> <jsp-api.version>2.2</jsp-api.version> <httpclient.version>4.5.10</httpclient.version> <joda-time.version>2.9.9</joda-time.version> <commons-lang3.version>3.9</commons-lang3.version> <commons-io.version>2.5</commons-io.version> <commons-net.version>3.6</commons-net.version> <commons-fileupload.version>1.4</commons-fileupload.version> <jedis.version>3.1.0</jedis.version> <solrj.version>7.7.2</solrj.version> </properties> <dependencyManagement> <dependencies> <!-- 单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </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.version}</version> </dependency> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <!-- MyBatis持久层框架 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis.spring.version}</version> </dependency> <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artifactId> <version>${mybatis.paginator.version}</version> </dependency> <!-- 通用Mapper --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>${mapper.version}</version> </dependency> <!-- 分页助手 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> <!-- JSqlParser parses an SQL statement and translate it --> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>${jsqlparser.version}</version> </dependency> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- 连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- Jackson Json处理工具包 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <!-- httpclient --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>${httpclient.version}</version> </dependency> <!-- JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet-api.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <!-- 时间操作组件 --> <dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>${joda-time.version}</version> </dependency> <!-- Apache工具组件 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>${commons-lang3.version}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>${commons-io.version}</version> </dependency> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>${commons-net.version}</version> </dependency> <!-- 文件上传组件 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version> </dependency> <!-- Redis客户端 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency> <!-- solr检索客户端 --> <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>${solrj.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <finalName>${project.artifactId}</finalName> <plugins> <!-- 资源文件拷贝插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.1.0</version><!-- Apr, 2018 --> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- java编译插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version><!-- May, 2019 --> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> <pluginManagement> <plugins> <!-- 配置Tomcat7插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> </plugin> <!-- eclipse执行maven install命令时跳过test --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <skip>true</skip> </configuration> </plugin> </plugins> </pluginManagement> <!-- <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> --> </build> <repositories> <repository> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>
通过Eclipse开发工具,去运行pom.xml导入的tomcat7插件
webapp目录下的WEB-INF文件夹里的web.xml配置springMVC拦截的url-pattern只有三种格式
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <display-name>itcast-usermanage</display-name> <!--重新指定spring配置文件的路径--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/applicationContext-*.xml</param-value> </context-param> <!--Spring的ApplicationContext 载入 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 编码过滤器,以UTF8编码 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 解决PUT请求无法提交表单数据的问题 --> <filter> <filter-name>HttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>HttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 将POST请求转化为DELETE或者是PUT 要用_method指定真正的请求方法 --> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 配置SpringMVC框架入口 --> <servlet> <servlet-name>itcast-usermanage</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/itcast-usermanage-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>itcast-usermanage</servlet-name> <!-- 可行:/、*.xxx、/xxx/* 不行:/* --> <url-pattern>/rest/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
applicationContext-dao.xml配置Druid数据库连接池,
并且使用更新版的通用Mapper和Pagehelper分页插件。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 加载配置文件,可以使用占位符替换功能 --> <context:property-placeholder location="classpath:properties/*.properties" ignore-unresolvable="true" /> <!-- 定义dataSource数据源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <!-- 数据库驱动 --> <property name="driverClassName" value="${jdbc.driver}" /> <!-- 相应驱动的jdbcUrl --> <property name="url" value="${jdbc.url}" /> <!-- 数据库的用户名 --> <property name="username" value="${jdbc.username}" /> <!-- 数据库的密码 --> <property name="password" value="${jdbc.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize" value="5" /> <property name="minIdle" value="5" /> <property name="maxActive" value="10" /> <!-- 配置从连接池获取连接等待超时的时间,单位是毫秒 --> <property name="maxWait" value="10000" /> <!-- 配置间隔多久启动一次DestroyThread,对连接池内的连接才进行一次检测,单位是毫秒。 检测时:1.如果连接空闲并且超过minIdle以外的连接,如果空闲时间超过minEvictableIdleTimeMillis设置的值则直接物理关闭。 2.在minIdle以内的不处理。 --> <property name="timeBetweenEvictionRunsMillis" value="600000" /> <!-- 配置一个连接在池中最大空闲时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="300000" /> <!-- 设置从连接池获取连接时是否检查连接有效性,true时,每次都检查;false时,不检查 --> <property name="testOnBorrow" value="false" /> <!-- 设置往连接池归还连接时是否检查连接有效性,true时,每次都检查;false时,不检查 --> <property name="testOnReturn" value="false" /> <!-- 设置从连接池获取连接时是否检查连接有效性, true时,如果连接空闲时间超过minEvictableIdleTimeMillis进行检查,否则不检查; false时,不检查 --> <property name="testWhileIdle" value="true" /> </bean> <!-- 让spring管理sqlSessionFactory 使用mybatis和spring整合包中的 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 数据库连接池 --> <property name="dataSource" ref="dataSource" /> <!-- 加载mybatis的全局配置文件 --> <property name="configLocation" value="classpath:mybatis/mybatis-config.xml" /> <!-- 实体类别名包 --> <property name="typeAliasesPackage" value="cn.itcast.usermanage.pojo"/> <!-- 配置mapper.xml文件 --> <!-- <property name="mapperLocations" value="classpath*:mybatis/mappers/*Mapper.xml"/> --> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect=mysql reasonable=true rowBoundsWithCount=true </value> </property> </bean> </array> </property> </bean> <!-- 配置扫描接口包,加载通用mapper代理对象 --> <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 扫描多个包地址 --> <property name="basePackage" value="cn.itcast.usermanage.mapper" /> </bean> </beans>
applicationContext-transaction.xml的配置中查询方法需要更完善补充一些
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 定义事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源 --> <property name="dataSource" ref="dataSource" /> </bean> <!-- 定义事务策略 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 属性propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择 --> <!--所有查询的方法都是只读的 --> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="select*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> <tx:method name="query*" propagation="SUPPORTS" read-only="true" /> <!--其他方法使用默认事务策略 --> <tx:method name="*" /> </tx:attributes> </tx:advice> <aop:config> <!--pointcut元素定义一个切入点,execution中的第一个星号 用以匹配方法的返回类型, 这里星号表明匹配所有返回类型。 com.abc.dao.*.*(..)表明匹配cn.itcast.mybatis.service包下的所有类的所有 方法 --> <aop:pointcut id="myPointcut" expression="execution(* cn.itcast.usermanage.service.*.*(..))" /> <!--将定义好的事务处理策略应用到上述的切入点表达式 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" /> </aop:config> </beans>
使用国内中央仓库镜像下载依赖需要先配置maven的配置文件,然后去项目的pom.xml里导入。
setting.xml <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> pom.xml <repositories> <repository> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
在SSM整合中使用通用Mapper插件的步骤是:
1.用maven导入相关的依赖坐标
<!-- Mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> </dependency> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- 分页助手 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> </dependency> <!-- JSqlParser parses an SQL statement and translate it --> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> </dependency> <!-- 通用Mapper --> <dependency> <groupId>com.github.abel533</groupId> <artifactId>mapper</artifactId> </dependency>
2.在applicationContext-dao.xml里配置通用Mapper插件(参考上面配置数据源的代码)
3.要在pojo实体类上与数据库表字段做注解映射(4.1.5版通用Mapper主键自增要用@KeySql)
@Table(name = "tb_user") public class User { @Id @KeySql(useGeneratedKeys = true) private Long id; // 用户名 @Column(name = "user_name") private String userName; // 密码 private String password; // 姓名 private String name; // 年龄 private Integer age; // 性别,1男性,2女性 private Integer sex; // 出生日期 private Date birthday;
视频里的通用Mapper的版本太旧了,在实体类pojo使用注解的方法声明主键自增可以参考:通用mapper主键策略
springMVC的Controller方法和jquery-easyui-1.4的ajax请求url之间的匹配问题
展示用户列表的jsp页面请求URL=IP地址+tomcat端口+web.xml里配置的(/rest/)+ 自动跳转Controller类窄化路径(page) + JSP页面的文件名(springmvc.xml视图解析器)
但是jquery-easyui-1.4发送ajax请求的url最终是一个相对路径: IP地址+tomcat端口+web.xml里配置的(/rest/)+ 之前已经在浏览器地址栏已有的(page)+ url( rest/user/list )
因此最后我们查询用户列表的Controller的完整URL和视频课里不一样,在Controller类的上面要有@RequestMapping("page")
但是当jquery-easyui-1.4的ajax请求url在第一个字符串是“/”的情况,就表示它发送的是完整绝对路径,即服务器IP地址+tomcat端口+Controller的类和方法的RequestMapping
通用Mapper插件可以实现按数据库字段(对应的pojo属性)的降序排序查询
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public EasyUIResult queryUserList(Integer page, Integer rows) { // 设置分页参数 PageHelper.startPage(page, rows); // 查询所有用户数据信息 //List<User> userList = userMapper.selectAll(); Example example = new Example(User.class); //example.setOrderByClause("updated"); //设置排序条件,升序 example.setOrderByClause("updated DESC"); //设置排序条件,降序 List<User> userList = userMapper.selectByExample(example); // 获取分页后的信息 PageInfo<User> pageInfo = new PageInfo<>(userList); // EasyUIResult提供了全参构造方法 return new EasyUIResult(pageInfo.getTotal(),pageInfo.getList()); } }
带返回状态码的HTTP请求Controller编写:
@RequestMapping("new/user") @Controller public class NewUserController { @Autowired private UserService userService; // 根据用户id查询用户信息 @GetMapping(value = "{id}") @ResponseBody public ResponseEntity<User> queryUserById(@PathVariable("id") Integer id) { try { // TODO Auto-generated method stub User user = userService.queryUserById(id); if (null == user) { // 资源不存在,响应404 return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); } // 资源存在,响应200 return ResponseEntity.ok(user); } catch (Exception e) { // 出现异常返回500状态码 e.printStackTrace(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); } } }
Service层插入方法返回一个int类型转换成 Boolean类型 通过==判断
@Override public Boolean insertUser(User user) { // 调用通用Mapper的插入方法 // 且通过 == 判断取得布尔值 return this.userMapper.insert(user) == 1; }
web.xml配置拦截器实现PUT和DELETE请求
<!-- 解决PUT请求无法提交表单数据的问题 --> <filter> <filter-name>HttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>HttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 将POST请求转化为DELETE或者是PUT 要用_method指定真正的请求方法 --> <filter> <filter-name>HiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>HiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
JSP页面文件中PUT请求的form表单书写格式可以参考:https://www.cnblogs.com/mki-mki/p/7406121.html
===========================================
参考资料: