在實戰中學習,模仿博客園的部分功能。包括用戶的注冊,登陸;發表新隨筆,閱讀隨筆;發表評論,以及定時任務等。Entity層設計3張表,分別為user表(用戶),essay表(隨筆)以及comment表(評論)。表結構如下:



項目開發采用Intellij IDEA + maven,整個項目結構如下如下圖所示:

在項目的pom.xml文件中,導入項目需要的依賴。pom.xml內容如下所示:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3 <modelVersion>4.0.0</modelVersion>
4 <groupId>spring_demo2</groupId>
5 <artifactId>com.everSeeker</artifactId>
6 <packaging>war</packaging>
7 <version>1.0</version>
8 <name>com.everSeeker Maven Webapp</name>
9 <url>http://maven.apache.org</url>
10
11 <properties>
12 <spring.version>4.2.4.RELEASE</spring.version>
13 <jetty.version>9.3.7.v20160115</jetty.version>
14 <slf4j.version>1.7.14</slf4j.version>
15 <jersey.version>1.19</jersey.version>
16 </properties>
17
18 <dependencies>
19
20 <!--數據庫相關, mysql, mybatis-->
21 <dependency>
22 <groupId>mysql</groupId>
23 <artifactId>mysql-connector-java</artifactId>
24 <version>5.1.38</version>
25 </dependency>
26 <dependency>
27 <groupId>org.mybatis</groupId>
28 <artifactId>mybatis</artifactId>
29 <version>3.3.0</version>
30 </dependency>
31 <dependency>
32 <groupId>org.mybatis</groupId>
33 <artifactId>mybatis-spring</artifactId>
34 <version>1.2.3</version>
35 </dependency>
36
37 <!--數據源配置, dataSource-->
38 <dependency>
39 <groupId>c3p0</groupId>
40 <artifactId>c3p0</artifactId>
41 <version>0.9.1.2</version>
42 </dependency>
43
44 <!--事務相關, transcationManager-->
45 <dependency>
46 <groupId>org.springframework</groupId>
47 <artifactId>spring-jdbc</artifactId>
48 <version>${spring.version}</version>
49 </dependency>
50
51 <!--可以找到使用Spring ApplicationContext特性時所需的全部類,JDNI 所需的全部類,instrumentation組件以及校驗Validation 方面的相關類。外部依賴spring-beans, (spring-aop)。-->
52 <!--提供基於注解的配置, 比如@Component, @Service, @Repository, @Controller等-->
53 <dependency>
54 <groupId>org.springframework</groupId>
55 <artifactId>spring-context</artifactId>
56 <version>${spring.version}</version>
57 </dependency>
58 <dependency>
59 <groupId>org.springframework</groupId>
60 <artifactId>spring-context-support</artifactId>
61 <version>${spring.version}</version>
62 </dependency>
63 <dependency>
64 <groupId>org.springframework</groupId>
65 <artifactId>spring-tx</artifactId>
66 <version>${spring.version}</version>
67 </dependency>
68
69 <!--測試-->
70 <dependency>
71 <groupId>junit</groupId>
72 <artifactId>junit</artifactId>
73 <version>4.12</version>
74 <scope>test</scope>
75 </dependency>
76 <dependency>
77 <groupId>org.springframework</groupId>
78 <artifactId>spring-test</artifactId>
79 <version>${spring.version}</version>
80 </dependency>
81
82 <!--任務調度-->
83 <dependency>
84 <groupId>org.quartz-scheduler</groupId>
85 <artifactId>quartz</artifactId>
86 <version>2.2.1</version>
87 </dependency>
88
89 <!--log4j && slf4j-->
90 <dependency>
91 <groupId>org.slf4j</groupId>
92 <artifactId>slf4j-api</artifactId>
93 <version>${slf4j.version}</version>
94 </dependency>
95 <dependency>
96 <groupId>org.slf4j</groupId>
97 <artifactId>slf4j-log4j12</artifactId>
98 <version>${slf4j.version}</version>
99 </dependency>
100 <dependency>
101 <groupId>org.slf4j</groupId>
102 <artifactId>jcl-over-slf4j</artifactId>
103 <version>${slf4j.version}</version>
104 <scope>runtime</scope>
105 </dependency>
106
107 <!--jetty相關-->
108 <dependency>
109 <groupId>org.eclipse.jetty</groupId>
110 <artifactId>jetty-server</artifactId>
111 <version>${jetty.version}</version>
112 </dependency>
113 <dependency>
114 <groupId>org.eclipse.jetty</groupId>
115 <artifactId>jetty-servlet</artifactId>
116 <version>${jetty.version}</version>
117 </dependency>
118 <dependency>
119 <groupId>org.eclipse.jetty</groupId>
120 <artifactId>jetty-webapp</artifactId>
121 <version>${jetty.version}</version>
122 </dependency>
123 <dependency>
124 <groupId>org.eclipse.jetty</groupId>
125 <artifactId>jetty-servlets</artifactId>
126 <version>${jetty.version}</version>
127 </dependency>
128
129 <!--jersey-->
130 <dependency>
131 <groupId>com.sun.jersey</groupId>
132 <artifactId>jersey-core</artifactId>
133 <version>${jersey.version}</version>
134 </dependency>
135 <dependency>
136 <groupId>com.sun.jersey.contribs</groupId>
137 <artifactId>jersey-spring</artifactId>
138 <version>${jersey.version}</version>
139 <exclusions>
140 <exclusion>
141 <artifactId>spring-core</artifactId>
142 <groupId>org.springframework</groupId>
143 </exclusion>
144 <exclusion>
145 <artifactId>spring-beans</artifactId>
146 <groupId>org.springframework</groupId>
147 </exclusion>
148 <exclusion>
149 <artifactId>spring-context</artifactId>
150 <groupId>org.springframework</groupId>
151 </exclusion>
152 <exclusion>
153 <artifactId>spring-web</artifactId>
154 <groupId>org.springframework</groupId>
155 </exclusion>
156 <exclusion>
157 <artifactId>spring-aop</artifactId>
158 <groupId>org.springframework</groupId>
159 </exclusion>
160 </exclusions>
161 </dependency>
162 <dependency>
163 <groupId>com.sun.jersey</groupId>
164 <artifactId>jersey-server</artifactId>
165 <version>${jersey.version}</version>
166 </dependency>
167 <dependency>
168 <groupId>com.sun.jersey</groupId>
169 <artifactId>jersey-servlet</artifactId>
170 <version>${jersey.version}</version>
171 </dependency>
172 <dependency>
173 <groupId>com.sun.jersey</groupId>
174 <artifactId>jersey-json</artifactId>
175 <version>${jersey.version}</version>
176 </dependency>
177
178 <!--用來將POJO序列化為JSON對象-->
179 <dependency>
180 <groupId>org.glassfish.jersey.media</groupId>
181 <artifactId>jersey-media-json-jackson</artifactId>
182 <version>2.22.2</version>
183 </dependency>
184
185 </dependencies>
186
187 <build>
188 <finalName>com.everSeeker</finalName>
189 </build>
190
191 </project>
注:以下所有介紹,第一步都是在pom.xml文件中導入相關依賴。之後文章中不再說明。
下面開始詳細介紹。
一、Mybatis
1、先做准備工作。在mysql數據庫中創建表。

2、在entity目錄下創建與數據庫中表對應的類,以user表為例。

3、在dao目錄下創建操作數據表的接口,以userDao為例。

4、為使用mybatis管理操作數據庫,首先需要設置spring與mybatis配合使用的相關配置。
mybatis.xml:在本項目中,僅僅用作給實體類配置別名。
spring-mybatis.xml:在本項目中,用來配置數據源dataSource,sqlSessionFactory等。
具體文件內容如下:


在spring-mybatis.xml文件中,引入了db.properties文件中的內容。

最後,在spring.xml配置文件中載入與mybatis相關的配置文件。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context.xsd"> 9 10 <!-- 加載Spring配置文件 --> 11 <context:property-placeholder location="classpath:db.properties"/> 12 <context:property-placeholder location="classpath:log4j.properties"/> 13 14 <import resource="classpath:spring-mybatis.xml"/> 15 16 <!-- 使用spring annotation自動掃描配置 --> 17 <context:component-scan base-package="com.everSeeker"/> 18 <!-- 自動注入 --> 19 <context:annotation-config/> 20 21 </beans>
5、准備工作已經完成,現在就可以通過在**Mapper.xml文件中以直接寫sql語句的方式來操作數據庫並同時實現dao層中相關類的接口了。以UserDao為例,在resources/com/everSeeker目錄下創建對應的UserMapper.xml文件。
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3
4 <mapper namespace="com.everSeeker.dao.UserDao">
5 <resultMap id="ResultMapUser" type="com.everSeeker.entity.User">
6 <id column="id" property="id"/>
7 <result column="username" property="username"/>
8 <result column="password" property="password"/>
9 <result column="score" property="score"/>
10 <result column="ranking" property="ranking"/>
11 <result column="essay_count" property="essayCount"/>
12 </resultMap>
13
14 <insert id="addUser" parameterType="User">
15 INSERT INTO user(username, password, score, ranking, essay_count) VALUES(#{user.username}, #{user.password}, #{user.score}, #{user.ranking}, #{user.essayCount})
16 </insert>
17
18 <select id="getUserById" parameterType="int" resultMap="ResultMapUser">
19 SELECT * FROM user WHERE id=#{id}
20 </select>
21
22 <select id="getUserByUsername" parameterType="String" resultMap="ResultMapUser">
23 SELECT * FROM user where username=#{username}
24 </select>
25
26 <update id="updateUser" parameterType="User">
27 UPDATE user SET username=#{username}, password=#{password}, score=#{score}, ranking=#{ranking}, essay_count=#{essayCount} where id=#{id}
28 </update>
29
30 <!--在mysql中執行多條語句,可以采用存儲過程,如{call proc()};也可以通過連接數據庫時設置allowMultiQueries=true來實現-->
31 <update id="rankingByScore">
32 -- { call proc() }
33 SET @row=0;
34 UPDATE user SET ranking=(@row:=@row+1) ORDER BY score DESC;
35 </update>
36 </mapper>
6、更多關於mybatis的內容參考:
1) http://www.mybatis.org/mybatis-3/zh/index.html
2) 如果數據表中的column字段和modal(entity)中定義的類的字段不一致,比如數據庫中User表有字段t_username,而在類User中定義字段username,則可以使用ResultMap來代替ResultType。詳細信息可參考MyBatis中關於resultType和resultMap的區別以及MyBatis魔法堂:ResultMap詳解以及MyBatis魔法堂:即學即用篇。
二、事務
在spring中實現事務可以很簡單。只需要配置好事務管理器,之後給需要事務處理的類或者方法直接通過@Transactional注解即可。
1、在本項目中,通過在spring-mybatis.xml文件中配置事務管理。
1 <!-- 事務管理器配置, 使用jdbc事務 --> 2 <bean id="transactionManager" 3 class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 4 <property name="dataSource" ref="dataSource" /> 5 </bean> 6 7 <!-- 使用annotation定義事務,對標注了@Transactional注解的bean進行處理,以織入事務管理切面. 8 默認情況下,自動使用名稱為transactionManager的事務管理器。 9 proxy-target-class為true,表示spring將通過創建子類來代理業務類,需要在類路徑中添加CGLib.jar類庫。--> 10 <tx:annotation-driven transaction-manager="transactionManager" 11 proxy-target-class="true" />
2、給需要事務處理的類或者方法通過@Transactional注解。以CommentServiceImpl.java為例,對類中所有方法進行事務處理。publicNewComment方法為發表新的評論,需要在comment表中新增一條評論的記錄,之後在essay表中對被評論的隨筆評論數+1,同時還需要在user表中對隨筆的作者score+10分,這3個操作組合成了一個原子操作,需要進行事務處理。
1 package com.everSeeker.service.impl;
2
3 import com.everSeeker.dao.CommentDao;
4 import com.everSeeker.dao.EssayDao;
5 import com.everSeeker.dao.UserDao;
6 import com.everSeeker.entity.Comment;
7 import com.everSeeker.entity.Essay;
8 import com.everSeeker.entity.User;
9 import com.everSeeker.service.CommentService;
10 import org.springframework.stereotype.Service;
11 import org.springframework.transaction.annotation.Transactional;
12
13 import javax.annotation.Resource;
14
15 @Service("commentService")
16 @Transactional
17 public class CommentServiceImpl implements CommentService {
18 @Resource
19 private CommentDao commentDao;
20 @Resource
21 private EssayDao essayDao;
22 @Resource
23 private UserDao userDao;
24
25 public void publishNewComment(Comment comment) {
26 //comment表中新增一條記錄
27 commentDao.addComment(comment);
28 //essay表comment_count+1
29 Essay essay = essayDao.getEssayById(comment.getEssayId());
30 if(essay != null) {
31 essay.setCommentCount(essay.getCommentCount() + 1);
32 essayDao.updateEssay(essay);
33 //user表隨筆作者對應的記錄score+10
34 User user = userDao.getUserById(essay.getUserId());
35 if(user != null) {
36 user.setScore(user.getScore() + 10);
37 userDao.updateUser(user);
38 }
39 }
40 }
41 }
三、JUnit4測試
使用JUnit4可以很方便的進行單元測試。假設我們需要對UserService類中的各個方法進行測試,只需要在test/com/everSeeker/service目錄下新建測試類TestUserService即可。
1、在測試類前面新增2個注解:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/spring.xml"})
@RunWith:加載JUnit4。
@ContextConfiguration:加載spring配置文件,是一個字符串數組,可以加載多個配置文件。
2、在具體方法前新增注解@Test。
TestUserService.java關鍵內容如下:
1 package com.everSeeker.service;
2
3 import com.everSeeker.dao.UserDao;
4 import com.everSeeker.entity.User;
5 import org.junit.Test;
6 import org.junit.runner.RunWith;
7 import org.springframework.test.annotation.Rollback;
8 import org.springframework.test.context.ContextConfiguration;
9 import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11
12 import javax.annotation.Resource;
13
14
15 @RunWith(SpringJUnit4ClassRunner.class)
16 @ContextConfiguration(locations = {"/spring.xml"})
17 public class TestUserService extends AbstractTransactionalJUnit4SpringContextTests {
18
19 @Resource
20 private UserService userService;
21
22 @Resource
23 private UserDao userDao;
24
25 /**
26 * AbstractTransactionalJUnit4SpringContextTests默認回滾。如果需要修改為不回滾設置為false即可。
27 * 默認回滾的主要目的是避免產生髒數據。但是如果數據庫主鍵采取自增模式的話,實質上對數據庫還是有一點影響。如果主鍵采取UUID就沒這個問題。
28 */
29 @Test
30 @Rollback(false)
31 public void TestAddUser() {
32 User user = new User("ponpon7", "888888");
33 userService.addUser(user);
34 }
35
36 @Test
37 public void TestGetUserByUsername() {
38 System.out.println(userService.getUserByUsername("ppp"));
39 }
40 }
四、日志(log4j & slf4j)
1、關鍵是配置好log4j.properties文件。
1 #更多詳情請參考:
2 #http://www.cnblogs.com/pigtail/archive/2013/02/16/2913195.html
3 #http://it.oyksoft.com/log4j/
4
5 #此句為將等級為INFO的日志信息輸出到stdout和R這兩個目的地,stdout和R的定義在下面的代碼,可以任意起名。
6 #等級可分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果配置OFF則不打出任何信息,
7 #如果配置為INFO這樣只顯示INFO, WARN, ERROR的log信息,而DEBUG信息不會被顯示,具體講解可參照第三部分定義配置文件中的logger。
8 log4j.rootCategory = INFO, R, stdout
9
10 #此句為定義名為stdout的輸出端是哪種類型,可以是
11 #org.apache.log4j.ConsoleAppender(控制台),
12 #org.apache.log4j.FileAppender(文件),
13 #org.apache.log4j.DailyRollingFileAppender(每天產生一個日志文件),
14 #org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產生一個新的文件)
15 #org.apache.log4j.WriterAppender(將日志信息以流格式發送到任意指定的地方)
16 log4j.appender.stdout = org.apache.log4j.ConsoleAppender
17
18 #此句為定義名為stdout的輸出端的layout是哪種類型,可以是
19 #org.apache.log4j.HTMLLayout(以HTML表格形式布局),
20 #org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
21 #org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串),
22 #org.apache.log4j.TTCCLayout(包含日志產生的時間、線程、類別等等信息)
23 #具體講解可參照第三部分定義配置文件中的Layout。
24 log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
25
26 #如果使用pattern布局就要指定的打印信息的具體格式ConversionPattern,打印參數如下:
27 #%m 輸出代碼中指定的消息
28 #%p 輸出優先級,即DEBUG,INFO,WARN,ERROR,FATAL
29 #%r 輸出自應用啟動到輸出該log信息耗費的毫秒數
30 #%c 輸出所屬的類目,通常就是所在類的全名
31 #%t 輸出產生該日志事件的線程名
32 #%n 輸出一個回車換行符,Windows平台為“rn”,Unix平台為“n”
33 #%d 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其後指定格式,比如:%d{yyyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
34 #%l 輸出日志事件的發生位置,包括類目名、發生的線程,以及在代碼中的行數。
35 #[QC]是log信息的開頭,可以為任意字符,一般為項目簡稱。
36 log4j.appender.stdout.layout.ConversionPattern = [%p]-[%t]-[%l]-[%d{yyyyMMdd HH:mm:ss}]%n%m%n
37
38 #將日志信息存入文件中
39 log4j.appender.R = org.apache.log4j.DailyRollingFileAppender
40 log4j.appender.R.Threshold = INFO
41 log4j.appender.R.File = /Users/pingping/Projects/IdeaProjects/cnblogs/spring_demo2/logs/output.log
42 log4j.appender.R.DatePattern = '.'yyyy-MM-dd
43 log4j.appender.R.Append = true
44 log4j.appender.R.layout = org.apache.log4j.PatternLayout
45 log4j.appender.R.layout.ConversionPattern = [%p]-[%t]-[%l]-[%d{yyyyMMdd HH:mm:ss}]%n%m%n
更多詳細信息可參考:
http://www.cnblogs.com/pigtail/archive/2013/02/16/2913195.html
http://it.oyksoft.com/log4j/
2、直接使用即可,以UserServiceImpl.java為例。
1 package com.everSeeker.service.impl;
2
3 import com.everSeeker.dao.UserDao;
4 import com.everSeeker.entity.User;
5 import com.everSeeker.service.UserService;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8 import org.springframework.stereotype.Service;
9
10 import javax.annotation.Resource;
11
12 @Service("userService")
13 public class UserServiceImpl implements UserService {
14 @Resource
15 private UserDao userDao;
16
17 private static Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
18
19 public void addUser(User user) {
20 userDao.addUser(user);
21 }
22
23 public User getUserByUsername(String username) {
24 User user = userDao.getUserByUsername(username);
25 log.info("All info about {}: \n{}", username, user);
26 return user;
27 }
28
29 public int checkUser(String username, String password) {
30 log.info("start check username: {}", username);
31 User user = userDao.getUserByUsername(username);
32 if (user == null) {
33 log.warn("username is incorrect!");
34 return 10;
35 }
36 if (!user.getPassword().equals(password)) {
37 log.warn("passowrd is incorrect!");
38 return 100;
39 }
40 log.info("{} has successed checked!", username);
41 return 1;
42 }
43 }
五、定時任務(Quartz & spring-task)
主要介紹目前主流的2種在指定時間執行或者按某個頻率自動執行的實現方式。
1、spring-task:采用@Scheduled注解方式,配置簡單,使用靈活方便。
2、quartz:配置稍微復雜,功能強大。
下面以具體代碼詳細說明。
首先,新創建spring-task.xml配置文件,具體內容如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:task="http://www.springframework.org/schema/task" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/task 8 http://www.springframework.org/schema/task/spring-task-3.0.xsd" 9 default-lazy-init="false"> 10 11 <!--開啟定時任務的2種方法,(1)通過spring-task,采用@Scheduled注解方式,配置簡單,使用靈活方便; 12 (2)通過quartz,配置稍微復雜,功能強大 --> 14 15 <!--方法一:--> 16 <!--開啟task:annotation-driven,spring可以通過注解@Scheduled來開啟任務--> 17 <task:executor id="executor" pool-size="5"/> 18 <task:scheduler id="scheduler" pool-size="10"/> 19 <task:annotation-driven executor="executor" scheduler="scheduler"/> 20 21 <!--方法二:--> 22 <!--配置作業類--> 23 <bean id="quartzTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> 24 <property name="targetObject"> 25 <bean class="com.everSeeker.task.QuartzTask"/> 26 </property> 27 <property name="targetMethod" value="rankingByScore"/> 28 <property name="concurrent" value="false"/> 29 </bean> 30 <!--配置觸發器--> 31 <!--關於cronExpression, 請參考: http://www.cnblogs.com/yaowen/p/3779284.html--> 32 <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"> 33 <property name="jobDetail" ref="quartzTask"/> 34 <!--每隔10s執行一次--> 35 <property name="cronExpression" value="0/10 * * * * ?"/> 36 </bean> 37 <!--配置調度工廠--> 38 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 39 <property name="triggers"> 40 <list> 41 <ref bean="cronTrigger"/> 42 </list> 43 </property> 44 </bean> 45 46 </beans>
在com/everSeeker/task目錄下新建2個文件QuartzTask.java以及SpringTask.java,分別用來測試quartz以及spring-task。
QuartzTask.java
1 package com.everSeeker.task;
2
3 import com.everSeeker.dao.UserDao;
4 import org.springframework.stereotype.Service;
5
6 import javax.annotation.Resource;
7
8 @Service
9 public class QuartzTask {
10 @Resource
11 private UserDao userDao;
12
13 public void rankingByScore() {
14 System.out.println("通過quartz, 每隔10s執行一次任務。。。");
15 // userDao.rankingByScore();
16 }
17 }
SpringTask.java
1 package com.everSeeker.task;
2
3 import com.everSeeker.dao.UserDao;
4 import org.springframework.scheduling.annotation.Scheduled;
5 import org.springframework.stereotype.Component;
6
7 import javax.annotation.Resource;
8
9 @Component("springTask")
10 public class SpringTask {
11
12 @Resource
13 private UserDao userDao;
14
15 @Scheduled(cron = "0/20 * * * * ?")
16 public void rankingByScoreJob() {
17 System.out.println("通過spring-task,每隔20秒執行一次任務。。。");
18 System.out.println("----------------------------------------");
19 // userDao.rankingByScore();
20 }
21 }
六、jetty
jetty需要定義Server, Connector以及至少一個handler, ThreadPool可選。
先定義自己的handler,內容是輸出"hello jetty"。
1 public class MyHandler extends AbstractHandler {
2
3 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
4 throws IOException, ServletException {
5 response.setContentType("text/html;charset=utf-8");
6 response.setStatus(HttpServletResponse.SC_OK);
7 baseRequest.setHandled(true);
8 response.getWriter().println("<h1>Hello jetty</h1>");
9 }
10 }
之後在Spring配置文件中將Server,Connector以及Handler配置好即可。
1 # spring-jetty.xml 2 <bean id="jetty_server" class="org.eclipse.jetty.server.Server" init-method="start" destroy-method="stop"> 3 4 <!--<property name="threadPool">--> 5 <!--<bean id="defaultThreadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">--> 6 <!--<property name="minThreads" value="10"/>--> 7 <!--<property name="maxThreads" value="100"/>--> 8 <!--</bean>--> 9 <!--</property>--> 10 11 <property name="connectors"> 12 <list> 13 <bean id="Connector" class="org.eclipse.jetty.server.ServerConnector"> 14 <constructor-arg name="server"><ref bean="jetty_server"/></constructor-arg> 15 <property name="port" value="8080"/> 16 </bean> 17 </list> 18 </property> 19 20 <property name="handler"> 21 <bean id="handlers" class="org.eclipse.jetty.server.handler.HandlerList"> 22 <property name="handlers"> 23 <list> 24 <bean class="com.everSeeker.jetty.MyHandler"/> 25 <!--<bean class="com.everSeeker.jetty.RestfulHandler"/>--> 26 <bean class="org.eclipse.jetty.server.handler.DefaultHandler"/> 27 </list> 28 </property> 29 </bean> 30 </property> 31 32 </bean>
在網頁中打開輸入網址, http://localhost:8080,頁面顯示為"hello jetty"。
更多詳情請參考:
http://www.eclipse.org/jetty/documentation/current/index.html
http://hbiao68.iteye.com/blog/2111007
http://www.cnblogs.com/windlaughing/archive/2013/06/07/3125358.html
七、Restful(jersey)
實現Restful的框架很多,本案例采用的是jersey.
首先建立一個jetty服務,並指定要處理jersey資源的包名com.everSeeker.action,然後啟動jetty。
public class App {
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
ServletHolder servlet = new ServletHolder(ServletContainer.class);
servlet.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");
servlet.setInitParameter("com.sun.jersey.config.property.packages", "com.everSeeker");
ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.SESSIONS);
handler.setContextPath("/");
handler.addServlet(servlet, "/*");
server.setHandler(handler);
server.start();
server.join();
}
}
之後在包com.everSeeker.action下新建Restful類,以UserAction.java為例。
1 @Component
2 @Path("/user")
3 public class UserAction {
4
5 /**
6 * 如果userService不采用getBean方式獲得的話,即直接寫成private UserService userService,會報空指針錯誤。
7 * 通過debug方式查看會發現,userService=null,沒有注入成功,原因暫時還不知道,請高手告知。
8 */
9 @Resource
10 private UserService userService = SpringContextUtils.getApplicationContext().getBean(UserServiceImpl.class);
11
12 /**
13 * @GET : get請求
14 * @Path : 路徑,由於類的路徑為/user,所以該方法的路徑為/user/{username}
15 * @Produces : 返回類型。該方法為文本。
16 * @Consumes : 可以接受的類型。
17 */
18 @GET
19 @Path("{username}")
20 @Produces(MediaType.TEXT_PLAIN)
21 public String getByUsername(@PathParam("username") String username) throws Exception {
22 return userService.getUserByUsername(username).toString();
23 }
24
25 /**
26 * 返回的類型為json。需要將類User轉換為json格式。本案例采用的轉換方式為jackson, 在pom.xml中有說明。
27 */
28 @GET
29 @Path("json/{username}")
30 @Produces(MediaType.APPLICATION_JSON)
31 public User getUserByUsername(@PathParam("username") String username) throws Exception {
32 return userService.getUserByUsername(username);
33 }
34 }
更多信息請參考:
https://jersey.java.net/nonav/documentation/latest/index.html
http://www.zhaochao.net/index.php/2015/12/07/5/
http://waylau.com/jersey-2-spring-4-rest/
代碼清單請見個人github。地址:https://github.com/ponpon7/spring_demo2。